From 0178724a2065922e77466496940cb09a5d7ec5e8 Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Thu, 27 Jun 2024 21:21:49 +0000 Subject: [PATCH 01/13] SDK regeneration --- .github/workflows/ci.yml | 3 +- poetry.lock | 341 +- pyproject.toml | 37 +- reference.md | 7234 +++++++++++++++++ src/webflow/__init__.py | 56 +- src/webflow/client.py | 84 +- src/webflow/core/__init__.py | 8 + src/webflow/core/client_wrapper.py | 42 +- src/webflow/core/http_client.py | 475 ++ src/webflow/core/jsonable_encoder.py | 18 +- src/webflow/core/pydantic_utilities.py | 28 + src/webflow/core/query_encoder.py | 33 + src/webflow/core/remove_none_from_dict.py | 4 +- src/webflow/core/request_options.py | 7 +- src/webflow/resources/__init__.py | 32 +- src/webflow/resources/access_groups/client.py | 190 +- src/webflow/resources/assets/client.py | 1082 ++- src/webflow/resources/collections/__init__.py | 22 +- src/webflow/resources/collections/client.py | 670 +- .../collections/resources/__init__.py | 19 +- .../collections/resources/fields/client.py | 370 +- .../fields/types/field_create_type.py | 8 +- .../collections/resources/items/__init__.py | 16 +- .../collections/resources/items/client.py | 2568 +++--- .../resources/items/types/__init__.py | 13 +- .../types/bulk_collection_item_field_data.py | 29 +- .../items_list_items_live_request_sort_by.py | 25 + ...tems_list_items_live_request_sort_order.py | 17 + .../types/items_list_items_request_sort_by.py | 25 + .../items_list_items_request_sort_order.py | 17 + .../types/items_publish_item_response.py | 30 - src/webflow/resources/ecommerce/client.py | 146 +- src/webflow/resources/forms/client.py | 736 +- src/webflow/resources/inventory/client.py | 356 +- src/webflow/resources/orders/__init__.py | 4 +- src/webflow/resources/orders/client.py | 1081 ++- .../resources/orders/types/__init__.py | 3 +- .../types/orders_list_request_status.py | 37 + src/webflow/resources/pages/__init__.py | 4 +- src/webflow/resources/pages/client.py | 1124 +-- .../pages/resources/scripts/client.py | 509 +- src/webflow/resources/pages/types/__init__.py | 3 +- .../pages/types/dom_write_nodes_item.py | 27 +- .../types/update_static_content_response.py | 32 + src/webflow/resources/products/__init__.py | 30 +- src/webflow/resources/products/client.py | 1324 ++- .../resources/products/types/__init__.py | 30 +- .../types/product_sku_create_product.py | 50 - .../product_sku_create_product_field_data.py | 52 - ...eate_product_field_data_ec_product_type.py | 33 - ..._create_product_field_data_tax_category.py | 133 - .../products/types/product_sku_create_sku.py | 46 - .../product_sku_create_sku_field_data.py | 62 - ..._create_sku_field_data_compare_at_price.py | 33 - ...te_sku_field_data_ec_sku_billing_method.py | 21 - ...sku_field_data_ec_sku_subscription_plan.py | 39 - ..._data_ec_sku_subscription_plan_interval.py | 33 - ...product_sku_create_sku_field_data_price.py | 34 - .../types/products_create_sku_response.py | 17 +- src/webflow/resources/scripts/client.py | 563 +- src/webflow/resources/sites/client.py | 531 +- .../sites/resources/activity_logs/client.py | 160 +- .../sites/resources/scripts/client.py | 673 +- src/webflow/resources/token/client.py | 181 +- src/webflow/resources/users/client.py | 838 +- .../users/types/users_update_request_data.py | 45 +- src/webflow/resources/webhooks/client.py | 540 +- src/webflow/types/__init__.py | 28 +- src/webflow/types/access_group.py | 58 +- src/webflow/types/access_group_list.py | 51 +- src/webflow/types/asset.py | 86 +- src/webflow/types/asset_folder.py | 71 +- src/webflow/types/asset_folder_list.py | 26 +- src/webflow/types/asset_upload.py | 75 +- .../types/asset_upload_upload_details.py | 37 +- src/webflow/types/asset_variant.py | 65 +- src/webflow/types/assets.py | 17 +- src/webflow/types/authorization.py | 23 +- .../types/authorization_authorization.py | 66 +- ...thorization_authorization_authorized_to.py | 39 +- src/webflow/types/authorized_user.py | 41 +- src/webflow/types/bad_request_error_body.py | 8 + src/webflow/types/collection.py | 70 +- src/webflow/types/collection_item.py | 74 +- .../types/collection_item_field_data.py | 29 +- src/webflow/types/collection_item_list.py | 25 +- .../types/collection_item_list_pagination.py | 32 +- src/webflow/types/collection_list.py | 24 +- .../types/collection_list_array_item.py | 63 +- src/webflow/types/conflict_error_body.py | 8 + src/webflow/types/custom_code_block.py | 57 +- .../types/custom_code_hosted_response.py | 73 + .../types/custom_code_inline_response.py | 73 + src/webflow/types/custom_code_response.py | 60 - src/webflow/types/dom.py | 24 +- src/webflow/types/domain.py | 26 +- src/webflow/types/domains.py | 20 +- src/webflow/types/duplicate_user_email.py | 36 +- src/webflow/types/ecommerce_settings.py | 41 +- src/webflow/types/error.py | 43 +- src/webflow/types/field.py | 68 +- src/webflow/types/field_type.py | 8 +- src/webflow/types/forbidden_error_body.py | 35 + src/webflow/types/form.py | 105 +- src/webflow/types/form_field_value.py | 47 +- src/webflow/types/form_list.py | 17 +- src/webflow/types/form_response_settings.py | 57 +- src/webflow/types/form_submission.py | 65 +- src/webflow/types/form_submission_list.py | 17 +- src/webflow/types/image_node.py | 20 +- src/webflow/types/inventory_item.py | 39 +- src/webflow/types/list_custom_code_blocks.py | 17 +- src/webflow/types/locale.py | 69 + src/webflow/types/locales.py | 38 + src/webflow/types/missing_scopes.py | 37 +- src/webflow/types/node.py | 28 +- src/webflow/types/not_enterprise_plan_site.py | 37 +- src/webflow/types/oauth_scope.py | 16 + src/webflow/types/order.py | 275 +- src/webflow/types/order_address.py | 81 +- src/webflow/types/order_address_japan_type.py | 2 +- src/webflow/types/order_customer_info.py | 31 +- .../types/order_download_files_item.py | 38 +- src/webflow/types/order_list.py | 23 +- src/webflow/types/order_metadata.py | 20 +- src/webflow/types/order_price.py | 36 +- src/webflow/types/order_purchased_item.py | 126 +- .../order_purchased_item_variant_image.py | 21 +- ...order_purchased_item_variant_image_file.py | 65 +- ...d_item_variant_image_file_variants_item.py | 41 +- src/webflow/types/order_totals.py | 36 +- src/webflow/types/order_totals_extras_item.py | 46 +- src/webflow/types/page.py | 123 +- src/webflow/types/page_details.py | 115 + src/webflow/types/page_details_open_graph.py | 53 + src/webflow/types/page_details_seo.py | 41 + src/webflow/types/page_list.py | 17 +- src/webflow/types/page_open_graph.py | 51 +- src/webflow/types/page_seo.py | 32 +- src/webflow/types/pagination.py | 34 +- src/webflow/types/paypal_details.py | 67 +- src/webflow/types/product.py | 71 +- src/webflow/types/product_and_sk_us.py | 22 +- src/webflow/types/product_and_sk_us_list.py | 26 +- src/webflow/types/product_field_data.py | 90 +- src/webflow/types/registered_script_list.py | 24 +- src/webflow/types/script_apply.py | 42 +- src/webflow/types/script_apply_list.py | 37 +- src/webflow/types/site.py | 99 +- src/webflow/types/site_activity_log_item.py | 32 +- .../types/site_activity_log_item_user.py | 20 +- .../types/site_activity_log_response.py | 17 +- src/webflow/types/sites.py | 30 + src/webflow/types/sku.py | 57 +- src/webflow/types/sku_field_data.py | 67 +- .../types/sku_field_data_compare_at_price.py | 28 +- ...sku_field_data_ec_sku_subscription_plan.py | 37 +- ...ata_ec_sku_subscription_plan_plans_item.py | 43 + ...sku_subscription_plan_plans_item_status.py | 29 + src/webflow/types/sku_field_data_price.py | 28 +- src/webflow/types/sku_property_list.py | 36 +- .../types/sku_property_list_enum_item.py | 34 +- src/webflow/types/stripe_card.py | 49 +- src/webflow/types/stripe_card_expires.py | 28 +- src/webflow/types/stripe_details.py | 81 +- src/webflow/types/text_node.py | 17 +- src/webflow/types/user.py | 78 +- src/webflow/types/user_access_groups_item.py | 39 +- src/webflow/types/user_data.py | 17 +- src/webflow/types/user_data_data.py | 59 +- src/webflow/types/user_limit_reached.py | 36 +- src/webflow/types/user_list.py | 46 +- src/webflow/types/users_not_enabled.py | 36 +- src/webflow/types/webhook.py | 78 +- src/webflow/types/webhook_list.py | 17 +- src/webflow/version.py | 4 + tests/__init__.py | 0 tests/{ => custom}/test_client.py | 0 tests/utils/test_http_client.py | 47 + tests/utils/test_query_encoding.py | 13 + 180 files changed, 18132 insertions(+), 9978 deletions(-) create mode 100644 reference.md create mode 100644 src/webflow/core/http_client.py create mode 100644 src/webflow/core/pydantic_utilities.py create mode 100644 src/webflow/core/query_encoder.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_by.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_order.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_by.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_order.py delete mode 100644 src/webflow/resources/collections/resources/items/types/items_publish_item_response.py create mode 100644 src/webflow/resources/orders/types/orders_list_request_status.py create mode 100644 src/webflow/resources/pages/types/update_static_content_response.py delete mode 100644 src/webflow/resources/products/types/product_sku_create_product.py delete mode 100644 src/webflow/resources/products/types/product_sku_create_product_field_data.py delete mode 100644 src/webflow/resources/products/types/product_sku_create_product_field_data_ec_product_type.py delete mode 100644 src/webflow/resources/products/types/product_sku_create_product_field_data_tax_category.py delete mode 100644 src/webflow/resources/products/types/product_sku_create_sku.py delete mode 100644 src/webflow/resources/products/types/product_sku_create_sku_field_data.py delete mode 100644 src/webflow/resources/products/types/product_sku_create_sku_field_data_compare_at_price.py delete mode 100644 src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_billing_method.py delete mode 100644 src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_subscription_plan.py delete mode 100644 src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_subscription_plan_interval.py delete mode 100644 src/webflow/resources/products/types/product_sku_create_sku_field_data_price.py create mode 100644 src/webflow/types/bad_request_error_body.py create mode 100644 src/webflow/types/conflict_error_body.py create mode 100644 src/webflow/types/custom_code_hosted_response.py create mode 100644 src/webflow/types/custom_code_inline_response.py delete mode 100644 src/webflow/types/custom_code_response.py create mode 100644 src/webflow/types/forbidden_error_body.py create mode 100644 src/webflow/types/locale.py create mode 100644 src/webflow/types/locales.py create mode 100644 src/webflow/types/page_details.py create mode 100644 src/webflow/types/page_details_open_graph.py create mode 100644 src/webflow/types/page_details_seo.py create mode 100644 src/webflow/types/sites.py create mode 100644 src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py create mode 100644 src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item_status.py create mode 100644 src/webflow/version.py delete mode 100644 tests/__init__.py rename tests/{ => custom}/test_client.py (100%) create mode 100644 tests/utils/test_http_client.py create mode 100644 tests/utils/test_query_encoding.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b26bf2..bb1b2d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,8 +32,9 @@ jobs: curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 - name: Install dependencies run: poetry install + - name: Test - run: poetry run pytest . + run: poetry run pytest ./tests/custom/ publish: needs: [compile, test] diff --git a/poetry.lock b/poetry.lock index d0145b2..a257797 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,14 +1,14 @@ -# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "annotated-types" -version = "0.6.0" +version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" files = [ - {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, - {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] [package.dependencies] @@ -16,13 +16,13 @@ typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} [[package]] name = "anyio" -version = "4.3.0" +version = "4.4.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.8" files = [ - {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, - {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, + {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, + {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, ] [package.dependencies] @@ -38,13 +38,13 @@ trio = ["trio (>=0.23)"] [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.6.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, + {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, ] [[package]] @@ -60,13 +60,13 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.2.0" +version = "1.2.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, - {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, + {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, + {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, ] [package.extras] @@ -130,13 +130,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "idna" -version = "3.6" +version = "3.7" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, ] [[package]] @@ -152,49 +152,48 @@ files = [ [[package]] name = "mypy" -version = "1.9.0" +version = "1.0.1" description = "Optional static typing for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"}, - {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"}, - {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"}, - {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"}, - {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"}, - {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"}, - {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"}, - {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"}, - {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"}, - {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"}, - {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"}, - {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"}, - {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"}, - {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"}, - {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"}, - {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"}, - {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"}, - {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"}, - {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"}, + {file = "mypy-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:71a808334d3f41ef011faa5a5cd8153606df5fc0b56de5b2e89566c8093a0c9a"}, + {file = "mypy-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:920169f0184215eef19294fa86ea49ffd4635dedfdea2b57e45cb4ee85d5ccaf"}, + {file = "mypy-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27a0f74a298769d9fdc8498fcb4f2beb86f0564bcdb1a37b58cbbe78e55cf8c0"}, + {file = "mypy-1.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:65b122a993d9c81ea0bfde7689b3365318a88bde952e4dfa1b3a8b4ac05d168b"}, + {file = "mypy-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:5deb252fd42a77add936b463033a59b8e48eb2eaec2976d76b6878d031933fe4"}, + {file = "mypy-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2013226d17f20468f34feddd6aae4635a55f79626549099354ce641bc7d40262"}, + {file = "mypy-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:48525aec92b47baed9b3380371ab8ab6e63a5aab317347dfe9e55e02aaad22e8"}, + {file = "mypy-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c96b8a0c019fe29040d520d9257d8c8f122a7343a8307bf8d6d4a43f5c5bfcc8"}, + {file = "mypy-1.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:448de661536d270ce04f2d7dddaa49b2fdba6e3bd8a83212164d4174ff43aa65"}, + {file = "mypy-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:d42a98e76070a365a1d1c220fcac8aa4ada12ae0db679cb4d910fabefc88b994"}, + {file = "mypy-1.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e64f48c6176e243ad015e995de05af7f22bbe370dbb5b32bd6988438ec873919"}, + {file = "mypy-1.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fdd63e4f50e3538617887e9aee91855368d9fc1dea30da743837b0df7373bc4"}, + {file = "mypy-1.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dbeb24514c4acbc78d205f85dd0e800f34062efcc1f4a4857c57e4b4b8712bff"}, + {file = "mypy-1.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a2948c40a7dd46c1c33765718936669dc1f628f134013b02ff5ac6c7ef6942bf"}, + {file = "mypy-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5bc8d6bd3b274dd3846597855d96d38d947aedba18776aa998a8d46fabdaed76"}, + {file = "mypy-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:17455cda53eeee0a4adb6371a21dd3dbf465897de82843751cf822605d152c8c"}, + {file = "mypy-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e831662208055b006eef68392a768ff83596035ffd6d846786578ba1714ba8f6"}, + {file = "mypy-1.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e60d0b09f62ae97a94605c3f73fd952395286cf3e3b9e7b97f60b01ddfbbda88"}, + {file = "mypy-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:0af4f0e20706aadf4e6f8f8dc5ab739089146b83fd53cb4a7e0e850ef3de0bb6"}, + {file = "mypy-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:24189f23dc66f83b839bd1cce2dfc356020dfc9a8bae03978477b15be61b062e"}, + {file = "mypy-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93a85495fb13dc484251b4c1fd7a5ac370cd0d812bbfc3b39c1bafefe95275d5"}, + {file = "mypy-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f546ac34093c6ce33f6278f7c88f0f147a4849386d3bf3ae193702f4fe31407"}, + {file = "mypy-1.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c6c2ccb7af7154673c591189c3687b013122c5a891bb5651eca3db8e6c6c55bd"}, + {file = "mypy-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:15b5a824b58c7c822c51bc66308e759243c32631896743f030daf449fe3677f3"}, + {file = "mypy-1.0.1-py3-none-any.whl", hash = "sha256:eda5c8b9949ed411ff752b9a01adda31afe7eae1e53e946dbdf9db23865e66c4"}, + {file = "mypy-1.0.1.tar.gz", hash = "sha256:28cea5a6392bb43d266782983b5a4216c25544cd7d80be681a155ddcdafd152d"}, ] [package.dependencies] -mypy-extensions = ">=1.0.0" +mypy-extensions = ">=0.4.3" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.1.0" +typing-extensions = ">=3.10" [package.extras] dmypy = ["psutil (>=4.0)"] install-types = ["pip"] -mypyc = ["setuptools (>=50)"] +python2 = ["typed-ast (>=1.4.0,<2)"] reports = ["lxml"] [[package]] @@ -210,24 +209,24 @@ files = [ [[package]] name = "packaging" -version = "24.0" +version = "24.1" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, - {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] [[package]] name = "pluggy" -version = "1.4.0" +version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" files = [ - {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, - {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] @@ -236,18 +235,18 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pydantic" -version = "2.6.4" +version = "2.7.4" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.6.4-py3-none-any.whl", hash = "sha256:cc46fce86607580867bdc3361ad462bab9c222ef042d3da86f2fb333e1d916c5"}, - {file = "pydantic-2.6.4.tar.gz", hash = "sha256:b1704e0847db01817624a6b86766967f552dd9dbf3afba4004409f908dcc84e6"}, + {file = "pydantic-2.7.4-py3-none-any.whl", hash = "sha256:ee8538d41ccb9c0a9ad3e0e5f07bf15ed8015b481ced539a1759d8cc89ae90d0"}, + {file = "pydantic-2.7.4.tar.gz", hash = "sha256:0c84efd9548d545f63ac0060c1e4d39bb9b14db8b3c0652338aecc07b5adec52"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.16.3" +pydantic-core = "2.18.4" typing-extensions = ">=4.6.1" [package.extras] @@ -255,90 +254,90 @@ email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.16.3" -description = "" +version = "2.18.4" +description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"}, - {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"}, - {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"}, - {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"}, - {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"}, - {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"}, - {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"}, - {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"}, - {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"}, - {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"}, - {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"}, - {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"}, - {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"}, - {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"}, - {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"}, - {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"}, - {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"}, - {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"}, - {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"}, - {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"}, - {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"}, - {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"}, - {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"}, - {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"}, - {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"}, - {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"}, - {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"}, - {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"}, - {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"}, - {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"}, - {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"}, - {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"}, - {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"}, - {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"}, - {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"}, - {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"}, - {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"}, - {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"}, - {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"}, - {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"}, + {file = "pydantic_core-2.18.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f76d0ad001edd426b92233d45c746fd08f467d56100fd8f30e9ace4b005266e4"}, + {file = "pydantic_core-2.18.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:59ff3e89f4eaf14050c8022011862df275b552caef8082e37b542b066ce1ff26"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a55b5b16c839df1070bc113c1f7f94a0af4433fcfa1b41799ce7606e5c79ce0a"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4d0dcc59664fcb8974b356fe0a18a672d6d7cf9f54746c05f43275fc48636851"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8951eee36c57cd128f779e641e21eb40bc5073eb28b2d23f33eb0ef14ffb3f5d"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4701b19f7e3a06ea655513f7938de6f108123bf7c86bbebb1196eb9bd35cf724"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e00a3f196329e08e43d99b79b286d60ce46bed10f2280d25a1718399457e06be"}, + {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97736815b9cc893b2b7f663628e63f436018b75f44854c8027040e05230eeddb"}, + {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6891a2ae0e8692679c07728819b6e2b822fb30ca7445f67bbf6509b25a96332c"}, + {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bc4ff9805858bd54d1a20efff925ccd89c9d2e7cf4986144b30802bf78091c3e"}, + {file = "pydantic_core-2.18.4-cp310-none-win32.whl", hash = "sha256:1b4de2e51bbcb61fdebd0ab86ef28062704f62c82bbf4addc4e37fa4b00b7cbc"}, + {file = "pydantic_core-2.18.4-cp310-none-win_amd64.whl", hash = "sha256:6a750aec7bf431517a9fd78cb93c97b9b0c496090fee84a47a0d23668976b4b0"}, + {file = "pydantic_core-2.18.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:942ba11e7dfb66dc70f9ae66b33452f51ac7bb90676da39a7345e99ffb55402d"}, + {file = "pydantic_core-2.18.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b2ebef0e0b4454320274f5e83a41844c63438fdc874ea40a8b5b4ecb7693f1c4"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a642295cd0c8df1b86fc3dced1d067874c353a188dc8e0f744626d49e9aa51c4"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f09baa656c904807e832cf9cce799c6460c450c4ad80803517032da0cd062e2"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98906207f29bc2c459ff64fa007afd10a8c8ac080f7e4d5beff4c97086a3dabd"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19894b95aacfa98e7cb093cd7881a0c76f55731efad31073db4521e2b6ff5b7d"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fbbdc827fe5e42e4d196c746b890b3d72876bdbf160b0eafe9f0334525119c8"}, + {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f85d05aa0918283cf29a30b547b4df2fbb56b45b135f9e35b6807cb28bc47951"}, + {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e85637bc8fe81ddb73fda9e56bab24560bdddfa98aa64f87aaa4e4b6730c23d2"}, + {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2f5966897e5461f818e136b8451d0551a2e77259eb0f73a837027b47dc95dab9"}, + {file = "pydantic_core-2.18.4-cp311-none-win32.whl", hash = "sha256:44c7486a4228413c317952e9d89598bcdfb06399735e49e0f8df643e1ccd0558"}, + {file = "pydantic_core-2.18.4-cp311-none-win_amd64.whl", hash = "sha256:8a7164fe2005d03c64fd3b85649891cd4953a8de53107940bf272500ba8a788b"}, + {file = "pydantic_core-2.18.4-cp311-none-win_arm64.whl", hash = "sha256:4e99bc050fe65c450344421017f98298a97cefc18c53bb2f7b3531eb39bc7805"}, + {file = "pydantic_core-2.18.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6f5c4d41b2771c730ea1c34e458e781b18cc668d194958e0112455fff4e402b2"}, + {file = "pydantic_core-2.18.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2fdf2156aa3d017fddf8aea5adfba9f777db1d6022d392b682d2a8329e087cef"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4748321b5078216070b151d5271ef3e7cc905ab170bbfd27d5c83ee3ec436695"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847a35c4d58721c5dc3dba599878ebbdfd96784f3fb8bb2c356e123bdcd73f34"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c40d4eaad41f78e3bbda31b89edc46a3f3dc6e171bf0ecf097ff7a0ffff7cb1"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:21a5e440dbe315ab9825fcd459b8814bb92b27c974cbc23c3e8baa2b76890077"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01dd777215e2aa86dfd664daed5957704b769e726626393438f9c87690ce78c3"}, + {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4b06beb3b3f1479d32befd1f3079cc47b34fa2da62457cdf6c963393340b56e9"}, + {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:564d7922e4b13a16b98772441879fcdcbe82ff50daa622d681dd682175ea918c"}, + {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0eb2a4f660fcd8e2b1c90ad566db2b98d7f3f4717c64fe0a83e0adb39766d5b8"}, + {file = "pydantic_core-2.18.4-cp312-none-win32.whl", hash = "sha256:8b8bab4c97248095ae0c4455b5a1cd1cdd96e4e4769306ab19dda135ea4cdb07"}, + {file = "pydantic_core-2.18.4-cp312-none-win_amd64.whl", hash = "sha256:14601cdb733d741b8958224030e2bfe21a4a881fb3dd6fbb21f071cabd48fa0a"}, + {file = "pydantic_core-2.18.4-cp312-none-win_arm64.whl", hash = "sha256:c1322d7dd74713dcc157a2b7898a564ab091ca6c58302d5c7b4c07296e3fd00f"}, + {file = "pydantic_core-2.18.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:823be1deb01793da05ecb0484d6c9e20baebb39bd42b5d72636ae9cf8350dbd2"}, + {file = "pydantic_core-2.18.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebef0dd9bf9b812bf75bda96743f2a6c5734a02092ae7f721c048d156d5fabae"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae1d6df168efb88d7d522664693607b80b4080be6750c913eefb77e34c12c71a"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9899c94762343f2cc2fc64c13e7cae4c3cc65cdfc87dd810a31654c9b7358cc"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99457f184ad90235cfe8461c4d70ab7dd2680e28821c29eca00252ba90308c78"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18f469a3d2a2fdafe99296a87e8a4c37748b5080a26b806a707f25a902c040a8"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cdf28938ac6b8b49ae5e92f2735056a7ba99c9b110a474473fd71185c1af5d"}, + {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:938cb21650855054dc54dfd9120a851c974f95450f00683399006aa6e8abb057"}, + {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:44cd83ab6a51da80fb5adbd9560e26018e2ac7826f9626bc06ca3dc074cd198b"}, + {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:972658f4a72d02b8abfa2581d92d59f59897d2e9f7e708fdabe922f9087773af"}, + {file = "pydantic_core-2.18.4-cp38-none-win32.whl", hash = "sha256:1d886dc848e60cb7666f771e406acae54ab279b9f1e4143babc9c2258213daa2"}, + {file = "pydantic_core-2.18.4-cp38-none-win_amd64.whl", hash = "sha256:bb4462bd43c2460774914b8525f79b00f8f407c945d50881568f294c1d9b4443"}, + {file = "pydantic_core-2.18.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:44a688331d4a4e2129140a8118479443bd6f1905231138971372fcde37e43528"}, + {file = "pydantic_core-2.18.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a2fdd81edd64342c85ac7cf2753ccae0b79bf2dfa063785503cb85a7d3593223"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86110d7e1907ab36691f80b33eb2da87d780f4739ae773e5fc83fb272f88825f"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46387e38bd641b3ee5ce247563b60c5ca098da9c56c75c157a05eaa0933ed154"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:123c3cec203e3f5ac7b000bd82235f1a3eced8665b63d18be751f115588fea30"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc1803ac5c32ec324c5261c7209e8f8ce88e83254c4e1aebdc8b0a39f9ddb443"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53db086f9f6ab2b4061958d9c276d1dbe3690e8dd727d6abf2321d6cce37fa94"}, + {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abc267fa9837245cc28ea6929f19fa335f3dc330a35d2e45509b6566dc18be23"}, + {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a0d829524aaefdebccb869eed855e2d04c21d2d7479b6cada7ace5448416597b"}, + {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:509daade3b8649f80d4e5ff21aa5673e4ebe58590b25fe42fac5f0f52c6f034a"}, + {file = "pydantic_core-2.18.4-cp39-none-win32.whl", hash = "sha256:ca26a1e73c48cfc54c4a76ff78df3727b9d9f4ccc8dbee4ae3f73306a591676d"}, + {file = "pydantic_core-2.18.4-cp39-none-win_amd64.whl", hash = "sha256:c67598100338d5d985db1b3d21f3619ef392e185e71b8d52bceacc4a7771ea7e"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:574d92eac874f7f4db0ca653514d823a0d22e2354359d0759e3f6a406db5d55d"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1f4d26ceb5eb9eed4af91bebeae4b06c3fb28966ca3a8fb765208cf6b51102ab"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77450e6d20016ec41f43ca4a6c63e9fdde03f0ae3fe90e7c27bdbeaece8b1ed4"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d323a01da91851a4f17bf592faf46149c9169d68430b3146dcba2bb5e5719abc"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43d447dd2ae072a0065389092a231283f62d960030ecd27565672bd40746c507"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:578e24f761f3b425834f297b9935e1ce2e30f51400964ce4801002435a1b41ef"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:81b5efb2f126454586d0f40c4d834010979cb80785173d1586df845a632e4e6d"}, + {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ab86ce7c8f9bea87b9d12c7f0af71102acbf5ecbc66c17796cff45dae54ef9a5"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:90afc12421df2b1b4dcc975f814e21bc1754640d502a2fbcc6d41e77af5ec312"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:51991a89639a912c17bef4b45c87bd83593aee0437d8102556af4885811d59f5"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:293afe532740370aba8c060882f7d26cfd00c94cae32fd2e212a3a6e3b7bc15e"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48ece5bde2e768197a2d0f6e925f9d7e3e826f0ad2271120f8144a9db18d5c8"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eae237477a873ab46e8dd748e515c72c0c804fb380fbe6c85533c7de51f23a8f"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:834b5230b5dfc0c1ec37b2fda433b271cbbc0e507560b5d1588e2cc1148cf1ce"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e858ac0a25074ba4bce653f9b5d0a85b7456eaddadc0ce82d3878c22489fa4ee"}, + {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2fd41f6eff4c20778d717af1cc50eca52f5afe7805ee530a4fbd0bae284f16e9"}, + {file = "pydantic_core-2.18.4.tar.gz", hash = "sha256:ec3beeada09ff865c344ff3bc2f427f5e6c26401cc6113d77e372c3fdac73864"}, ] [package.dependencies] @@ -366,6 +365,49 @@ tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +[[package]] +name = "pytest-asyncio" +version = "0.23.7" +description = "Pytest support for asyncio" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_asyncio-0.23.7-py3-none-any.whl", hash = "sha256:009b48127fbe44518a547bddd25611551b0e43ccdbf1e67d12479f569832c20b"}, + {file = "pytest_asyncio-0.23.7.tar.gz", hash = "sha256:5f5c72948f4c49e7db4f29f2521d4031f1c27f86e57b046126654083d4770268"}, +] + +[package.dependencies] +pytest = ">=7.0.0,<9" + +[package.extras] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] +testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + [[package]] name = "sniffio" version = "1.3.1" @@ -388,18 +430,29 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20240316" +description = "Typing stubs for python-dateutil" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types-python-dateutil-2.9.0.20240316.tar.gz", hash = "sha256:5d2f2e240b86905e40944dd787db6da9263f0deabef1076ddaed797351ec0202"}, + {file = "types_python_dateutil-2.9.0.20240316-py3-none-any.whl", hash = "sha256:6b8cb66d960771ce5ff974e9dd45e38facb81718cc1e208b10b1baccbfdbee3b"}, +] + [[package]] name = "typing-extensions" -version = "4.10.0" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, - {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "3c8fae8de68e5484c48073bf191e51acbe3b9a32fd98e6b5e4d165e42a7fc7aa" +content-hash = "7fa2085bd251148908cf9a89f13b158fe85ccb037bb44614ae5f150ceecee53c" diff --git a/pyproject.toml b/pyproject.toml index 2ade12a..ca24275 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,13 +1,35 @@ [tool.poetry] name = "webflow" -version = "v1.2.0" +version = "1.2.2" description = "" readme = "README.md" authors = [] +keywords = [] + +classifiers = [ + "Intended Audience :: Developers", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Operating System :: OS Independent", + "Operating System :: POSIX", + "Operating System :: MacOS", + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows", + "Topic :: Software Development :: Libraries :: Python Modules", + "Typing :: Typed" +] packages = [ { include = "webflow", from = "src"} ] +[project.urls] +Repository = 'https://github.com/webflow/webflow-python' + [tool.poetry.dependencies] python = "^3.8" httpx = ">=0.21.2" @@ -15,8 +37,19 @@ pydantic = ">= 1.9.2" typing_extensions = ">= 4.0.0" [tool.poetry.dev-dependencies] -mypy = "^1.8.0" +mypy = "1.0.1" pytest = "^7.4.0" +pytest-asyncio = "^0.23.5" +python-dateutil = "^2.9.0" +types-python-dateutil = "^2.9.0.20240316" + +[tool.pytest.ini_options] +testpaths = [ "tests" ] +asyncio_mode = "auto" + +[tool.mypy] +plugins = ["pydantic.mypy"] + [build-system] requires = ["poetry-core"] diff --git a/reference.md b/reference.md new file mode 100644 index 0000000..5110fae --- /dev/null +++ b/reference.md @@ -0,0 +1,7234 @@ +# Reference +## Token +
client.token.authorized_by() +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Information about the Authorized User

Required Scope | `authorized_user:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.token.authorized_by() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.token.introspect() +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Information about the authorization token
Access to this endpoint requires a bearer token from a Data Client App.
+
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.token.introspect() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Sites +
client.sites.list() +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List of all sites the provided access token is able to access.

Required scope | `sites:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.list() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get a site by site id

Required scope | `sites:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.get( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.get_custom_domain(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get a list of all custom domains related to site.

Required scope | `sites:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.get_custom_domain( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.publish(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Publish a site to one more more domains.

Required scope | `sites:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.publish( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**custom_domains:** `typing.Optional[typing.Sequence[str]]` — Array of Custom Domain ids to publish + +
+
+ +
+
+ +**publish_to_webflow_subdomain:** `typing.Optional[bool]` — Choice of whether to publish to the default Webflow Subdomain + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Sites ActivityLogs +
client.sites.activity_logs.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.activity_logs.list( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Collections +
client.collections.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List of all Collections within a Site.

Required scope | `cms:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.list( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.create(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create a Collection for a site.

Required scope | `cms:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.create( + site_id="site_id", + display_name="Blog Posts", + singular_name="Blog Post", + slug="posts", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**display_name:** `str` — Name of the collection. Each collection name must be distinct. + +
+
+ +
+
+ +**singular_name:** `str` — Singular name of each item. + +
+
+ +
+
+ +**slug:** `typing.Optional[str]` — Part of a URL that identifier + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get the full details of a collection from its ID.

Required scope | `cms:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.get( + collection_id="collection_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.delete_collection(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Delete a collection using its ID.

Required scope | `cms:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.delete_collection( + collection_id="collection_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.delete(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Delete a custom field in a collection. This endpoint does not currently support bulk deletion.

Required scope | `cms:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.delete( + collection_id="collection_id", + field_id="field_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**field_id:** `str` — Unique identifier for a Field in a collection + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Collections Fields +
client.collections.fields.create(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create a custom field in a collection.

Slugs must be all lowercase letters without spaces. If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will convert the slug to lowercase and replace spaces with "-."

Only some field types can be created through the API. This endpoint does not currently support bulk creation.

Required scope | `cms:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow +from webflow.resources.collections import FieldCreateType + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.fields.create( + collection_id="collection_id", + is_required=False, + type=FieldCreateType.RICH_TEXT, + display_name="Post Body", + help_text="Add the body of your post here", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**type:** `FieldCreateType` — Choose these appropriate field type for your collection data + +
+
+ +
+
+ +**display_name:** `str` — The name of a field + +
+
+ +
+
+ +**is_required:** `typing.Optional[bool]` — define whether a field is required in a collection + +
+
+ +
+
+ +**help_text:** `typing.Optional[str]` — Additional text to help anyone filling out this field + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.fields.update(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update a custom field in a collection.

Required scope | `cms:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.fields.update( + collection_id="collection_id", + field_id="field_id", + is_required=False, + display_name="Post Body", + help_text="Add the body of your post here", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**field_id:** `str` — Unique identifier for a Field in a collection + +
+
+ +
+
+ +**is_required:** `typing.Optional[bool]` — Define whether a field is required in a collection + +
+
+ +
+
+ +**display_name:** `typing.Optional[str]` — The name of a field + +
+
+ +
+
+ +**help_text:** `typing.Optional[str]` — Additional text to help anyone filling out this field + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Collections Items +
client.collections.items.list_items(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List of all Items within a Collection.

Required scope | `CMS:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.list_items( + collection_id="collection_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**name:** `typing.Optional[str]` — The name of the item(s) + +
+
+ +
+
+ +**slug:** `typing.Optional[str]` — The slug of the item + +
+
+ +
+
+ +**sort_by:** `typing.Optional[ItemsListItemsRequestSortBy]` — Sort results by the provided value + +
+
+ +
+
+ +**sort_order:** `typing.Optional[ItemsListItemsRequestSortOrder]` — Sorts the results by asc or desc + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.items.create_item(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create Item in a Collection.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import CollectionItemFieldData +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.create_item( + collection_id="collection_id", + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**id:** `str` — Unique identifier for the Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item + +
+
+ +
+
+ +**last_published:** `typing.Optional[str]` — The date the item was last published + +
+
+ +
+
+ +**last_updated:** `typing.Optional[str]` — The date the item was last updated + +
+
+ +
+
+ +**created_on:** `typing.Optional[str]` — The date the item was created + +
+
+ +
+
+ +**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived + +
+
+ +
+
+ +**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft + +
+
+ +
+
+ +**field_data:** `typing.Optional[CollectionItemFieldData]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.items.list_items_live(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List of all live Items within a Collection.

Required scope | `CMS:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.list_items_live( + collection_id="collection_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**name:** `typing.Optional[str]` — The name of the item(s) + +
+
+ +
+
+ +**slug:** `typing.Optional[str]` — The slug of the item + +
+
+ +
+
+ +**sort_by:** `typing.Optional[ItemsListItemsLiveRequestSortBy]` — Sort results by the provided value + +
+
+ +
+
+ +**sort_order:** `typing.Optional[ItemsListItemsLiveRequestSortOrder]` — Sorts the results by asc or desc + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.items.create_item_live(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create live Item in a Collection. This Item will be published to the live site.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import CollectionItemFieldData +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.create_item_live( + collection_id="collection_id", + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**id:** `str` — Unique identifier for the Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item + +
+
+ +
+
+ +**last_published:** `typing.Optional[str]` — The date the item was last published + +
+
+ +
+
+ +**last_updated:** `typing.Optional[str]` — The date the item was last updated + +
+
+ +
+
+ +**created_on:** `typing.Optional[str]` — The date the item was created + +
+
+ +
+
+ +**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived + +
+
+ +
+
+ +**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft + +
+
+ +
+
+ +**field_data:** `typing.Optional[CollectionItemFieldData]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.items.create_item_for_multiple_locales(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create single Item in a Collection with multiple corresponding locales.

Required scope | `CMS:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.create_item_for_multiple_locales( + collection_id="collection_id", + id="580e64008c9a982ac9b8b754", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**id:** `str` — Unique identifier for the Item + +
+
+ +
+
+ +**cms_locale_ids:** `typing.Optional[typing.Sequence[str]]` — Array of identifiers for the locales where the item will be created + +
+
+ +
+
+ +**last_published:** `typing.Optional[str]` — The date the item was last published + +
+
+ +
+
+ +**last_updated:** `typing.Optional[str]` — The date the item was last updated + +
+
+ +
+
+ +**created_on:** `typing.Optional[str]` — The date the item was created + +
+
+ +
+
+ +**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived + +
+
+ +
+
+ +**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft + +
+
+ +
+
+ +**field_data:** `typing.Optional[BulkCollectionItemFieldData]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.items.get_item(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get details of a selected Collection Item.

Required scope | `CMS:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.get_item( + collection_id="collection_id", + item_id="item_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.items.delete_item(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Delete an Item from a Collection. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.delete_item( + collection_id="collection_id", + item_id="item_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.items.update_item(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update a selected Item in a Collection.

Required scope | `CMS:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import CollectionItemFieldData +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.update_item( + collection_id="collection_id", + item_id="item_id", + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**id:** `str` — Unique identifier for the Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item + +
+
+ +
+
+ +**last_published:** `typing.Optional[str]` — The date the item was last published + +
+
+ +
+
+ +**last_updated:** `typing.Optional[str]` — The date the item was last updated + +
+
+ +
+
+ +**created_on:** `typing.Optional[str]` — The date the item was created + +
+
+ +
+
+ +**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived + +
+
+ +
+
+ +**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft + +
+
+ +
+
+ +**field_data:** `typing.Optional[CollectionItemFieldData]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.items.get_item_live(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get details of a selected Collection live Item.

Required scope | `CMS:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.get_item_live( + collection_id="collection_id", + item_id="item_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.items.delete_item_live(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.delete_item_live( + collection_id="collection_id", + item_id="item_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.items.update_item_live(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update a selected live Item in a Collection. The updates for this Item will be published to the live site.

Required scope | `CMS:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import CollectionItemFieldData +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.update_item_live( + collection_id="collection_id", + item_id="item_id", + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**id:** `str` — Unique identifier for the Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item + +
+
+ +
+
+ +**last_published:** `typing.Optional[str]` — The date the item was last published + +
+
+ +
+
+ +**last_updated:** `typing.Optional[str]` — The date the item was last updated + +
+
+ +
+
+ +**created_on:** `typing.Optional[str]` — The date the item was created + +
+
+ +
+
+ +**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived + +
+
+ +
+
+ +**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft + +
+
+ +
+
+ +**field_data:** `typing.Optional[CollectionItemFieldData]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.collections.items.publish_item(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Publish an item or multiple items.

Required scope | `cms:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.collections.items.publish_item( + collection_id="collection_id", + item_ids=["itemIds"], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_ids:** `typing.Sequence[str]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Pages +
client.pages.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List of all pages for a site

Required scope | `pages:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.list( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**locale:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.pages.get_metadata(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get metadata information for a single page

Required scope | `pages:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.get_metadata( + page_id="page_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**locale:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.pages.update_page_settings(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update Page-level metadata, including SEO and Open Graph fields.

Required scope | `pages:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime + +from webflow import PageOpenGraph, PageSeo +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.update_page_settings( + page_id="page_id", + id="6596da6045e56dee495bcbba", + site_id="6258612d1ee792848f805dcf", + title="Guide to the Galaxy", + slug="guide-to-the-galaxy", + parent_id="6419db964a9c435aa3af6251", + collection_id="6390c49774a71f12831a08e3", + created_on=datetime.datetime.fromisoformat( + "2024-03-11 10:42:00+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2024-03-11 10:42:42+00:00", + ), + archived=False, + draft=False, + can_branch=True, + seo=PageSeo( + title="The Ultimate Hitchhiker's Guide to the Galaxy", + description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", + ), + open_graph=PageOpenGraph( + title="Explore the Cosmos with The Ultimate Guide", + title_copied=False, + description="Dive deep into the mysteries of the universe with your guide to everything galactic.", + description_copied=False, + ), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**locale:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. + +
+
+ +
+
+ +**id:** `typing.Optional[str]` — Unique identifier for the Page + +
+
+ +
+
+ +**site_id:** `typing.Optional[str]` — Unique identifier for the Site + +
+
+ +
+
+ +**title:** `typing.Optional[str]` — Title of the Page + +
+
+ +
+
+ +**slug:** `typing.Optional[str]` — slug of the Page (derived from title) + +
+
+ +
+
+ +**parent_id:** `typing.Optional[str]` — Identifier of the parent folder + +
+
+ +
+
+ +**collection_id:** `typing.Optional[str]` — Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. + +
+
+ +
+
+ +**created_on:** `typing.Optional[dt.datetime]` — The date the Page was created + +
+
+ +
+
+ +**last_updated:** `typing.Optional[dt.datetime]` — The date the Page was most recently updated + +
+
+ +
+
+ +**archived:** `typing.Optional[bool]` — Whether the Page has been archived + +
+
+ +
+
+ +**draft:** `typing.Optional[bool]` — Whether the Page is a draft + +
+
+ +
+
+ +**can_branch:** `typing.Optional[bool]` — Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) + +
+
+ +
+
+ +**is_members_only:** `typing.Optional[bool]` — Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) + +
+
+ +
+
+ +**seo:** `typing.Optional[PageSeo]` — SEO-related fields for the Page + +
+
+ +
+
+ +**open_graph:** `typing.Optional[PageOpenGraph]` — Open Graph fields for the Page + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.pages.get_content(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get static content from a static page.
If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale

Required scope | `pages:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.get_content( + page_id="page_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**locale:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.pages.update_static_content(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update static content on a static page. This endpoint supports sending 1000 nodes per request.

Required scope | `pages:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import DomWriteNodesItem +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.update_static_content( + page_id="page_id", + locale="locale", + nodes=[ + DomWriteNodesItem( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", + text="

The Hitchhiker's Guide to the Galaxy

", + ), + DomWriteNodesItem( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + DomWriteNodesItem( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + text="Marvin, the Paranoid Android", + ), + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**locale:** `str` — The locale identifier. + +
+
+ +
+
+ +**nodes:** `typing.Sequence[DomWriteNodesItem]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Pages Scripts +
client.pages.scripts.get_custom_code(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get all registered scripts that have been applied to a specific Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.scripts.get_custom_code( + page_id="page_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.pages.scripts.upsert_custom_code(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Add a registered script to a Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import ScriptApply, ScriptApplyLocation +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.scripts.upsert_custom_code( + page_id="page_id", + scripts=[ + ScriptApply( + id="cms_slider", + location=ScriptApplyLocation.HEADER, + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location=ScriptApplyLocation.HEADER, + version="0.0.1", + ), + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page + +
+
+ +
+
+ +**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated + +
+
+ +
+
+ +**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.pages.scripts.delete_custom_code(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Delete the custom code block that an app has created for a page

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.scripts.delete_custom_code( + page_id="page_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Sites Scripts +
client.sites.scripts.get_custom_code(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get all registered scripts that have been applied to a specific Site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.scripts.get_custom_code( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.scripts.upsert_custom_code(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Add a registered script to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import ScriptApply, ScriptApplyLocation +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.scripts.upsert_custom_code( + site_id="site_id", + scripts=[ + ScriptApply( + id="cms_slider", + location=ScriptApplyLocation.HEADER, + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location=ScriptApplyLocation.HEADER, + version="0.0.1", + ), + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page + +
+
+ +
+
+ +**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated + +
+
+ +
+
+ +**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.scripts.delete_custom_code(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Delete the custom code block that an app created for a Site

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.scripts.delete_custom_code( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.scripts.list_custom_code_blocks(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get all instances of Custom Code applied to a Site or Pages.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.scripts.list_custom_code_blocks( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Scripts +
client.scripts.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List of scripts registered to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.scripts.list( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.scripts.register_hosted(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Add a script to a Site's Custom Code registry.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.


Required scope | `custom_code:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.scripts.register_hosted( + site_id="site_id", + hosted_location="hostedLocation", + integrity_hash="integrityHash", + version="version", + display_name="displayName", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**hosted_location:** `str` — URI for an externally hosted script location + +
+
+ +
+
+ +**integrity_hash:** `str` — Sub-Resource Integrity Hash + +
+
+ +
+
+ +**version:** `str` — A Semantic Version (SemVer) string, denoting the version of the script + +
+
+ +
+
+ +**display_name:** `str` — User-facing name for the script. Must be between 1 and 50 alphanumeric characters + +
+
+ +
+
+ +**can_copy:** `typing.Optional[bool]` — Define whether the script can be copied on site duplication and transfer + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.scripts.register_inline(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.scripts.register_inline( + site_id="site_id", + source_code="alert('hello world');", + version="0.0.1", + display_name="Alert", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**source_code:** `str` — The code to be added to the site (to be hosted by Webflow). + +
+
+ +
+
+ +**version:** `str` — A Semantic Version (SemVer) string, denoting the version of the script + +
+
+ +
+
+ +**display_name:** `str` — User-facing name for the script. Must be between 1 and 50 alphanumeric characters + +
+
+ +
+
+ +**integrity_hash:** `typing.Optional[str]` — Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) + +
+
+ +
+
+ +**can_copy:** `typing.Optional[bool]` — Define whether the script can be copied on site duplication and transfer + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Assets +
client.assets.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List assets for a given site

Required scope | `assets:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.list( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.assets.create(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create a new asset entry.

This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) request to the `uploadUrl` with the `uploadDetails` object as your header information in the request.

Required scope | `assets:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.create( + site_id="site_id", + file_name="file.png", + file_hash="3c7d87c9575702bc3b1e991f4d3c638e", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**file_name:** `str` — file name including file extension + +
+
+ +
+
+ +**file_hash:** `str` — MD5 hash of the file + +
+
+ +
+
+ +**parent_folder:** `typing.Optional[str]` — id of the Asset folder (optional) + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.assets.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get an Asset

Required scope | `assets:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.get( + asset_id="asset_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**asset_id:** `str` — Unique identifier for an Asset on a site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.assets.delete(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Delete an Asset +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.delete( + asset_id="asset_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**asset_id:** `str` — Unique identifier for an Asset on a site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.assets.update(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update an Asset

Required scope | `assets:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.update( + asset_id="asset_id", + display_name="bulldoze.png", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**asset_id:** `str` — Unique identifier for an Asset on a site + +
+
+ +
+
+ +**display_name:** `str` — file name including file extension + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.assets.list_folders(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List Asset Folders within a given site

Required scope | `assets:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.list_folders( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.assets.create_folder(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create an Asset Folder within a given site

Required scope | `assets:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.create_folder( + site_id="site_id", + display_name="my asset folder", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**display_name:** `str` — A human readable name for the Asset Folder + +
+
+ +
+
+ +**parent_folder:** `typing.Optional[str]` — An (optional) pointer to a parent Asset Folder (or null for root) + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.assets.get_folder(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get details about a specific Asset Folder

Required scope | `assets:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.get_folder( + asset_folder_id="asset_folder_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**asset_folder_id:** `str` — Unique identifier for an Asset Folder + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Webhooks +
client.webhooks.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List all App-created Webhooks registered for a given site

Required scope | `sites:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.webhooks.list( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.webhooks.create(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create a new Webhook, to be notified when Webflow resources change. Limit of 75 registrations per `triggerType`, per site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `sites:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import TriggerType +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.webhooks.create( + site_id="site_id", + trigger_type=TriggerType.FORM_SUBMISSION, + url="https://api.mydomain.com/webhook", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**trigger_type:** `TriggerType` + +
+
+ +
+
+ +**url:** `str` — The server URI that Webflow will call when your Webhook is triggered + + +
+
+ +
+
+ +**filter:** `typing.Optional[typing.Dict[str, typing.Any]]` + +Filter for selecting which events you want Webhooks to be triggered for. +** Only available for `form_submission` trigger types. ** + + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.webhooks.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get a specific Webhook instance +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.webhooks.get( + webhook_id="webhook_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**webhook_id:** `str` — Unique identifier for a Webhook + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.webhooks.delete(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Remove a Webhook +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.webhooks.delete( + webhook_id="webhook_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**webhook_id:** `str` — Unique identifier for a Webhook + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Forms +
client.forms.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List forms for a given site

Required scope | `forms:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.forms.list( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.forms.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get information about a given form

Required scope | `forms:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.forms.get( + form_id="form_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**form_id:** `str` — Unique identifier for a Form + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.forms.list_submissions(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List form submissions for a given form

Required scope | `forms:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.forms.list_submissions( + form_id="form_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**form_id:** `str` — Unique identifier for a Form + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.forms.get_submission(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get information about a given form submission

Required scope | `forms:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.forms.get_submission( + form_submission_id="form_submission_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**form_submission_id:** `str` — Unique identifier for a Form Submission + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.forms.update_submission(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update hidden fields on a form submission

Required scope | `forms:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.forms.update_submission( + form_submission_id="form_submission_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**form_submission_id:** `str` — Unique identifier for a Form Submission + +
+
+ +
+
+ +**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Any]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Users +
client.users.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get a list of users for a site

Required scope | `users:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.users.list( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**sort:** `typing.Optional[UsersListRequestSort]` + +Sort string to use when ordering users + +Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). + +Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.users.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get a User by ID

Required scope | `users:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.users.get( + site_id="site_id", + user_id="user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**user_id:** `str` — Unique identifier for a User + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.users.delete(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Delete a User by ID

Required scope | `users:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.users.delete( + site_id="site_id", + user_id="user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**user_id:** `str` — Unique identifier for a User + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.users.update(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update a User by ID

Required scope | `users:write` + + +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import UsersUpdateRequestData +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.users.update( + site_id="site_id", + user_id="user_id", + data=UsersUpdateRequestData( + name="Some One", + accept_privacy=False, + accept_communications=False, + ), + access_groups=["webflowers", "platinum", "free-tier"], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**user_id:** `str` — Unique identifier for a User + +
+
+ +
+
+ +**data:** `typing.Optional[UsersUpdateRequestData]` + +
+
+ +
+
+ +**access_groups:** `typing.Optional[typing.Sequence[str]]` — An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. + + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.users.invite(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create and invite a user with an email address. The user will be sent and invite via email, which they will need to accept in order to join paid Access Groups.

Required scope | `users:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.users.invite( + site_id="site_id", + email="some.one@home.com", + access_groups=["webflowers"], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**email:** `str` — Email address of user to send invite to + +
+
+ +
+
+ +**access_groups:** `typing.Optional[typing.Sequence[str]]` — An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. + + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## AccessGroups +
client.access_groups.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get a list of access groups for a site

Required scope | `users:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.access_groups.list( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**sort:** `typing.Optional[AccessGroupsListRequestSort]` + +Sort string to use when ordering access groups +Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Products +
client.products.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve all products for a site. Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. + +Required scope | `ecommerce:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.products.list( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.products.create(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Creating a new Product involves creating both a Product and a SKU, since a Product Item has to have, at minimum, a single SKU. + +In order to create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large - you'll need to create `sku-properties`. In our T-shirt example, a single `sku-property` would be Color. Within that property, we'll need to list out the various colors a T-shirt could be as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. + +Once, you've created a Product and its `sku-properties` with `enum` values, you can create your default SKU, which will automatically be a combination of the first `sku-properties` you've created. In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. After you've created your product, you can create additional SKUs using the Create SKU endpoint + +Upon creation, the default product type will be `Advanced`. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. + +Required scope | `ecommerce:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.products.create( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**publish_status:** `typing.Optional[PublishStatus]` + +
+
+ +
+
+ +**product:** `typing.Optional[Product]` + +
+
+ +
+
+ +**sku:** `typing.Optional[Sku]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.products.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve a single product by its id. All of its SKUs will also be retrieved. + +Required scope | `ecommerce:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.products.get( + site_id="site_id", + product_id="product_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**product_id:** `str` — Unique identifier for a Product + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.products.update(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Updating an existing Product will set the product type to `Advanced`. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. + +Required scope | `ecommerce:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.products.update( + site_id="site_id", + product_id="product_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**product_id:** `str` — Unique identifier for a Product + +
+
+ +
+
+ +**publish_status:** `typing.Optional[PublishStatus]` + +
+
+ +
+
+ +**product:** `typing.Optional[Product]` + +
+
+ +
+
+ +**sku:** `typing.Optional[Sku]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.products.create_sku(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Create additional SKUs to cover every variant of your Product. The Default SKU already counts as one of the variants. + +Creating additional SKUs will set the product type to `Advanced` for the product associated with the SKUs. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. + +Required scope | `ecommerce:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Sku +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.products.create_sku( + site_id="site_id", + product_id="product_id", + skus=[Sku()], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**product_id:** `str` — Unique identifier for a Product + +
+
+ +
+
+ +**skus:** `typing.Sequence[Sku]` — An array of the SKU data your are adding + +
+
+ +
+
+ +**publish_status:** `typing.Optional[PublishStatus]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.products.update_sku(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Updating an existing SKU will set the product type to `Advanced` for the product associated with the SKU. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. + +Required scope | `ecommerce:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Sku +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.products.update_sku( + site_id="site_id", + product_id="product_id", + sku_id="sku_id", + sku=Sku(), +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**product_id:** `str` — Unique identifier for a Product + +
+
+ +
+
+ +**sku_id:** `str` — Unique identifier for a SKU + +
+
+ +
+
+ +**sku:** `Sku` + +
+
+ +
+
+ +**publish_status:** `typing.Optional[PublishStatus]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Orders +
client.orders.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List all orders created for a given site. + +Required scope | `ecommerce:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.orders.list( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**status:** `typing.Optional[OrdersListRequestStatus]` — Filter the orders by status + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.orders.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve a single product by its id. All of its SKUs will also be retrieved. + +Required scope | `ecommerce:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.orders.get( + site_id="site_id", + order_id="order_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**order_id:** `str` — Unique identifier for an Order + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.orders.update(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +This API lets you update the fields, `comment`, `shippingProvider`, and/or `shippingTracking` for a given order. All three fields can be updated simultaneously or independently. + +Required scope | `ecommerce:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.orders.update( + site_id="site_id", + order_id="order_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**order_id:** `str` — Unique identifier for an Order + +
+
+ +
+
+ +**comment:** `typing.Optional[str]` — Arbitrary data for your records + +
+
+ +
+
+ +**shipping_provider:** `typing.Optional[str]` — Company or method used to ship order + +
+
+ +
+
+ +**shipping_tracking:** `typing.Optional[str]` — Tracking number for order shipment + +
+
+ +
+
+ +**shipping_tracking_url:** `typing.Optional[str]` — URL to track order shipment + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.orders.update_fulfill(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Updates an order's status to fulfilled + +Required scope | `ecommerce:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.orders.update_fulfill( + site_id="site_id", + order_id="order_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**order_id:** `str` — Unique identifier for an Order + +
+
+ +
+
+ +**send_order_fulfilled_email:** `typing.Optional[bool]` — Whether or not the Order Fulfilled email should be sent + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.orders.update_unfulfill(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Updates an order's status to unfulfilled + +Required scope | `ecommerce:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.orders.update_unfulfill( + site_id="site_id", + order_id="order_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**order_id:** `str` — Unique identifier for an Order + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.orders.refund(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +This API will reverse a Stripe charge and refund an order back to a +customer. It will also set the order's status to `refunded`. + +Required scope | `ecommerce:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.orders.refund( + site_id="site_id", + order_id="order_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**order_id:** `str` — Unique identifier for an Order + +
+
+ +
+
+ +**reason:** `typing.Optional[OrdersRefundRequestReason]` — The reason for the refund + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Inventory +
client.inventory.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List the current inventory levels for a particular SKU item. + +Required scope | `ecommerce:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.inventory.list( + collection_id="collection_id", + item_id="item_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.inventory.update(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Updates the current inventory levels for a particular SKU item. Updates may be given in one or two methods, absolutely or incrementally. Absolute updates are done by setting `quantity` directly. Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. + +Required scope | `ecommerce:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import InventoryUpdateRequestInventoryType +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.inventory.update( + collection_id="collection_id", + item_id="item_id", + inventory_type=InventoryUpdateRequestInventoryType.INFINITE, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**inventory_type:** `InventoryUpdateRequestInventoryType` — infinite or finite + +
+
+ +
+
+ +**update_quantity:** `typing.Optional[float]` — Adds this quantity to currently store quantity. Can be negative. + +
+
+ +
+
+ +**quantity:** `typing.Optional[float]` — Immediately sets quantity to this value. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Ecommerce +
client.ecommerce.get_settings(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve ecommerce settings for a site. + +Required scope | `ecommerce:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow.client import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.ecommerce.get_settings( + site_id="site_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ diff --git a/src/webflow/__init__.py b/src/webflow/__init__.py index 7d4de99..45e46b7 100644 --- a/src/webflow/__init__.py +++ b/src/webflow/__init__.py @@ -15,6 +15,7 @@ AuthorizationAuthorization, AuthorizationAuthorizationAuthorizedTo, AuthorizedUser, + BadRequestErrorBody, Collection, CollectionItem, CollectionItemFieldData, @@ -22,9 +23,11 @@ CollectionItemListPagination, CollectionList, CollectionListArrayItem, + ConflictErrorBody, CustomCodeBlock, CustomCodeBlockType, - CustomCodeResponse, + CustomCodeHostedResponse, + CustomCodeInlineResponse, Dom, Domain, Domains, @@ -34,6 +37,7 @@ ErrorDetailsItem, Field, FieldType, + ForbiddenErrorBody, Form, FormField, FormFieldValue, @@ -47,6 +51,8 @@ InventoryItem, InventoryItemInventoryType, ListCustomCodeBlocks, + Locale, + Locales, MissingScopes, NoDomains, Node, @@ -72,6 +78,9 @@ OrderTotalsExtrasItem, OrderTotalsExtrasItemType, Page, + PageDetails, + PageDetailsOpenGraph, + PageDetailsSeo, PageList, PageOpenGraph, PageSeo, @@ -94,12 +103,15 @@ SiteActivityLogItemResourceOperation, SiteActivityLogItemUser, SiteActivityLogResponse, + Sites, Sku, SkuFieldData, SkuFieldDataCompareAtPrice, SkuFieldDataEcSkuBillingMethod, SkuFieldDataEcSkuSubscriptionPlan, SkuFieldDataEcSkuSubscriptionPlanInterval, + SkuFieldDataEcSkuSubscriptionPlanPlansItem, + SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus, SkuFieldDataPrice, SkuPropertyList, SkuPropertyListEnumItem, @@ -135,19 +147,10 @@ AccessGroupsListRequestSort, DomWriteNodesItem, InventoryUpdateRequestInventoryType, + OrdersListRequestStatus, OrdersRefundRequestReason, - ProductSkuCreateProduct, - ProductSkuCreateProductFieldData, - ProductSkuCreateProductFieldDataEcProductType, - ProductSkuCreateProductFieldDataTaxCategory, - ProductSkuCreateSku, - ProductSkuCreateSkuFieldData, - ProductSkuCreateSkuFieldDataCompareAtPrice, - ProductSkuCreateSkuFieldDataEcSkuBillingMethod, - ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlan, - ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval, - ProductSkuCreateSkuFieldDataPrice, ProductsCreateSkuResponse, + UpdateStaticContentResponse, UsersListRequestSort, UsersUpdateRequestData, access_groups, @@ -166,6 +169,7 @@ webhooks, ) from .environment import WebflowEnvironment +from .version import __version__ __all__ = [ "AccessGroup", @@ -184,6 +188,7 @@ "AuthorizationAuthorizationAuthorizedTo", "AuthorizedUser", "BadRequestError", + "BadRequestErrorBody", "Collection", "CollectionItem", "CollectionItemFieldData", @@ -192,9 +197,11 @@ "CollectionList", "CollectionListArrayItem", "ConflictError", + "ConflictErrorBody", "CustomCodeBlock", "CustomCodeBlockType", - "CustomCodeResponse", + "CustomCodeHostedResponse", + "CustomCodeInlineResponse", "Dom", "DomWriteNodesItem", "Domain", @@ -206,6 +213,7 @@ "Field", "FieldType", "ForbiddenError", + "ForbiddenErrorBody", "Form", "FormField", "FormFieldValue", @@ -221,6 +229,8 @@ "InventoryItemInventoryType", "InventoryUpdateRequestInventoryType", "ListCustomCodeBlocks", + "Locale", + "Locales", "MissingScopes", "NoDomains", "Node", @@ -246,8 +256,12 @@ "OrderTotals", "OrderTotalsExtrasItem", "OrderTotalsExtrasItemType", + "OrdersListRequestStatus", "OrdersRefundRequestReason", "Page", + "PageDetails", + "PageDetailsOpenGraph", + "PageDetailsSeo", "PageList", "PageOpenGraph", "PageSeo", @@ -259,17 +273,6 @@ "ProductFieldData", "ProductFieldDataEcProductType", "ProductFieldDataTaxCategory", - "ProductSkuCreateProduct", - "ProductSkuCreateProductFieldData", - "ProductSkuCreateProductFieldDataEcProductType", - "ProductSkuCreateProductFieldDataTaxCategory", - "ProductSkuCreateSku", - "ProductSkuCreateSkuFieldData", - "ProductSkuCreateSkuFieldDataCompareAtPrice", - "ProductSkuCreateSkuFieldDataEcSkuBillingMethod", - "ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlan", - "ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval", - "ProductSkuCreateSkuFieldDataPrice", "ProductsCreateSkuResponse", "PublishStatus", "RegisteredScriptList", @@ -282,12 +285,15 @@ "SiteActivityLogItemResourceOperation", "SiteActivityLogItemUser", "SiteActivityLogResponse", + "Sites", "Sku", "SkuFieldData", "SkuFieldDataCompareAtPrice", "SkuFieldDataEcSkuBillingMethod", "SkuFieldDataEcSkuSubscriptionPlan", "SkuFieldDataEcSkuSubscriptionPlanInterval", + "SkuFieldDataEcSkuSubscriptionPlanPlansItem", + "SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus", "SkuFieldDataPrice", "SkuPropertyList", "SkuPropertyListEnumItem", @@ -300,6 +306,7 @@ "TooManyRequestsError", "TriggerType", "UnauthorizedError", + "UpdateStaticContentResponse", "User", "UserAccessGroupsItem", "UserAccessGroupsItemType", @@ -314,6 +321,7 @@ "WebflowEnvironment", "Webhook", "WebhookList", + "__version__", "access_groups", "assets", "collections", diff --git a/src/webflow/client.py b/src/webflow/client.py index 493b3bd..2a602d9 100644 --- a/src/webflow/client.py +++ b/src/webflow/client.py @@ -24,21 +24,34 @@ class Webflow: """ - Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propogate to these functions. + Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions. - Parameters: - - base_url: typing.Optional[str]. The base url to use for requests from the client. + Parameters + ---------- + base_url : typing.Optional[str] + The base url to use for requests from the client. - - environment: WebflowEnvironment. The environment to use for requests from the client. from .environment import WebflowEnvironment + environment : WebflowEnvironment + The environment to use for requests from the client. from .environment import WebflowEnvironment - Defaults to WebflowEnvironment.DEFAULT - - access_token: typing.Union[str, typing.Callable[[], str]]. - - timeout: typing.Optional[float]. The timeout to be used, in seconds, for requests by default the timeout is 60 seconds. + Defaults to WebflowEnvironment.DEFAULT - - httpx_client: typing.Optional[httpx.Client]. The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. - --- + + + access_token : typing.Union[str, typing.Callable[[], str]] + timeout : typing.Optional[float] + The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced. + + follow_redirects : typing.Optional[bool] + Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in. + + httpx_client : typing.Optional[httpx.Client] + The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -52,13 +65,20 @@ def __init__( base_url: typing.Optional[str] = None, environment: WebflowEnvironment = WebflowEnvironment.DEFAULT, access_token: typing.Union[str, typing.Callable[[], str]], - timeout: typing.Optional[float] = 60, + timeout: typing.Optional[float] = None, + follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.Client] = None ): + _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None self._client_wrapper = SyncClientWrapper( base_url=_get_base_url(base_url=base_url, environment=environment), access_token=access_token, - httpx_client=httpx.Client(timeout=timeout) if httpx_client is None else httpx_client, + httpx_client=httpx_client + if httpx_client is not None + else httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects) + if follow_redirects is not None + else httpx.Client(timeout=_defaulted_timeout), + timeout=_defaulted_timeout, ) self.token = TokenClient(client_wrapper=self._client_wrapper) self.sites = SitesClient(client_wrapper=self._client_wrapper) @@ -78,21 +98,34 @@ def __init__( class AsyncWebflow: """ - Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propogate to these functions. + Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions. + + Parameters + ---------- + base_url : typing.Optional[str] + The base url to use for requests from the client. + + environment : WebflowEnvironment + The environment to use for requests from the client. from .environment import WebflowEnvironment + + + + Defaults to WebflowEnvironment.DEFAULT - Parameters: - - base_url: typing.Optional[str]. The base url to use for requests from the client. - - environment: WebflowEnvironment. The environment to use for requests from the client. from .environment import WebflowEnvironment - Defaults to WebflowEnvironment.DEFAULT + access_token : typing.Union[str, typing.Callable[[], str]] + timeout : typing.Optional[float] + The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced. - - access_token: typing.Union[str, typing.Callable[[], str]]. + follow_redirects : typing.Optional[bool] + Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in. - - timeout: typing.Optional[float]. The timeout to be used, in seconds, for requests by default the timeout is 60 seconds. + httpx_client : typing.Optional[httpx.AsyncClient] + The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. - - httpx_client: typing.Optional[httpx.AsyncClient]. The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -106,13 +139,20 @@ def __init__( base_url: typing.Optional[str] = None, environment: WebflowEnvironment = WebflowEnvironment.DEFAULT, access_token: typing.Union[str, typing.Callable[[], str]], - timeout: typing.Optional[float] = 60, + timeout: typing.Optional[float] = None, + follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.AsyncClient] = None ): + _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None self._client_wrapper = AsyncClientWrapper( base_url=_get_base_url(base_url=base_url, environment=environment), access_token=access_token, - httpx_client=httpx.AsyncClient(timeout=timeout) if httpx_client is None else httpx_client, + httpx_client=httpx_client + if httpx_client is not None + else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects) + if follow_redirects is not None + else httpx.AsyncClient(timeout=_defaulted_timeout), + timeout=_defaulted_timeout, ) self.token = AsyncTokenClient(client_wrapper=self._client_wrapper) self.sites = AsyncSitesClient(client_wrapper=self._client_wrapper) diff --git a/src/webflow/core/__init__.py b/src/webflow/core/__init__.py index 4c53b36..58ad52a 100644 --- a/src/webflow/core/__init__.py +++ b/src/webflow/core/__init__.py @@ -4,19 +4,27 @@ from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper from .datetime_utils import serialize_datetime from .file import File, convert_file_dict_to_httpx_tuples +from .http_client import AsyncHttpClient, HttpClient from .jsonable_encoder import jsonable_encoder +from .pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from .query_encoder import encode_query from .remove_none_from_dict import remove_none_from_dict from .request_options import RequestOptions __all__ = [ "ApiError", "AsyncClientWrapper", + "AsyncHttpClient", "BaseClientWrapper", "File", + "HttpClient", "RequestOptions", "SyncClientWrapper", "convert_file_dict_to_httpx_tuples", + "deep_union_pydantic_dicts", + "encode_query", "jsonable_encoder", + "pydantic_v1", "remove_none_from_dict", "serialize_datetime", ] diff --git a/src/webflow/core/client_wrapper.py b/src/webflow/core/client_wrapper.py index 59bbfde..f8b1535 100644 --- a/src/webflow/core/client_wrapper.py +++ b/src/webflow/core/client_wrapper.py @@ -4,17 +4,26 @@ import httpx +from .http_client import AsyncHttpClient, HttpClient + class BaseClientWrapper: - def __init__(self, *, access_token: typing.Union[str, typing.Callable[[], str]], base_url: str): + def __init__( + self, + *, + access_token: typing.Union[str, typing.Callable[[], str]], + base_url: str, + timeout: typing.Optional[float] = None, + ): self._access_token = access_token self._base_url = base_url + self._timeout = timeout def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { "X-Fern-Language": "Python", "X-Fern-SDK-Name": "webflow", - "X-Fern-SDK-Version": "v1.2.0", + "X-Fern-SDK-Version": "1.2.2", } headers["Authorization"] = f"Bearer {self._get_access_token()}" return headers @@ -28,13 +37,26 @@ def _get_access_token(self) -> str: def get_base_url(self) -> str: return self._base_url + def get_timeout(self) -> typing.Optional[float]: + return self._timeout + class SyncClientWrapper(BaseClientWrapper): def __init__( - self, *, access_token: typing.Union[str, typing.Callable[[], str]], base_url: str, httpx_client: httpx.Client + self, + *, + access_token: typing.Union[str, typing.Callable[[], str]], + base_url: str, + timeout: typing.Optional[float] = None, + httpx_client: httpx.Client, ): - super().__init__(access_token=access_token, base_url=base_url) - self.httpx_client = httpx_client + super().__init__(access_token=access_token, base_url=base_url, timeout=timeout) + self.httpx_client = HttpClient( + httpx_client=httpx_client, + base_headers=self.get_headers(), + base_timeout=self.get_timeout(), + base_url=self.get_base_url(), + ) class AsyncClientWrapper(BaseClientWrapper): @@ -43,7 +65,13 @@ def __init__( *, access_token: typing.Union[str, typing.Callable[[], str]], base_url: str, + timeout: typing.Optional[float] = None, httpx_client: httpx.AsyncClient, ): - super().__init__(access_token=access_token, base_url=base_url) - self.httpx_client = httpx_client + super().__init__(access_token=access_token, base_url=base_url, timeout=timeout) + self.httpx_client = AsyncHttpClient( + httpx_client=httpx_client, + base_headers=self.get_headers(), + base_timeout=self.get_timeout(), + base_url=self.get_base_url(), + ) diff --git a/src/webflow/core/http_client.py b/src/webflow/core/http_client.py new file mode 100644 index 0000000..09c6836 --- /dev/null +++ b/src/webflow/core/http_client.py @@ -0,0 +1,475 @@ +# This file was auto-generated by Fern from our API Definition. + +import asyncio +import email.utils +import json +import re +import time +import typing +import urllib.parse +from contextlib import asynccontextmanager, contextmanager +from random import random + +import httpx + +from .file import File, convert_file_dict_to_httpx_tuples +from .jsonable_encoder import jsonable_encoder +from .query_encoder import encode_query +from .remove_none_from_dict import remove_none_from_dict +from .request_options import RequestOptions + +INITIAL_RETRY_DELAY_SECONDS = 0.5 +MAX_RETRY_DELAY_SECONDS = 10 +MAX_RETRY_DELAY_SECONDS_FROM_HEADER = 30 + + +def _parse_retry_after(response_headers: httpx.Headers) -> typing.Optional[float]: + """ + This function parses the `Retry-After` header in a HTTP response and returns the number of seconds to wait. + + Inspired by the urllib3 retry implementation. + """ + retry_after_ms = response_headers.get("retry-after-ms") + if retry_after_ms is not None: + try: + return int(retry_after_ms) / 1000 if retry_after_ms > 0 else 0 + except Exception: + pass + + retry_after = response_headers.get("retry-after") + if retry_after is None: + return None + + # Attempt to parse the header as an int. + if re.match(r"^\s*[0-9]+\s*$", retry_after): + seconds = float(retry_after) + # Fallback to parsing it as a date. + else: + retry_date_tuple = email.utils.parsedate_tz(retry_after) + if retry_date_tuple is None: + return None + if retry_date_tuple[9] is None: # Python 2 + # Assume UTC if no timezone was specified + # On Python2.7, parsedate_tz returns None for a timezone offset + # instead of 0 if no timezone is given, where mktime_tz treats + # a None timezone offset as local time. + retry_date_tuple = retry_date_tuple[:9] + (0,) + retry_date_tuple[10:] + + retry_date = email.utils.mktime_tz(retry_date_tuple) + seconds = retry_date - time.time() + + if seconds < 0: + seconds = 0 + + return seconds + + +def _retry_timeout(response: httpx.Response, retries: int) -> float: + """ + Determine the amount of time to wait before retrying a request. + This function begins by trying to parse a retry-after header from the response, and then proceeds to use exponential backoff + with a jitter to determine the number of seconds to wait. + """ + + # If the API asks us to wait a certain amount of time (and it's a reasonable amount), just do what it says. + retry_after = _parse_retry_after(response.headers) + if retry_after is not None and retry_after <= MAX_RETRY_DELAY_SECONDS_FROM_HEADER: + return retry_after + + # Apply exponential backoff, capped at MAX_RETRY_DELAY_SECONDS. + retry_delay = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS) + + # Add a randomness / jitter to the retry delay to avoid overwhelming the server with retries. + timeout = retry_delay * (1 - 0.25 * random()) + return timeout if timeout >= 0 else 0 + + +def _should_retry(response: httpx.Response) -> bool: + retriable_400s = [429, 408, 409] + return response.status_code >= 500 or response.status_code in retriable_400s + + +def remove_omit_from_dict( + original: typing.Dict[str, typing.Optional[typing.Any]], omit: typing.Optional[typing.Any] +) -> typing.Dict[str, typing.Any]: + if omit is None: + return original + new: typing.Dict[str, typing.Any] = {} + for key, value in original.items(): + if value is not omit: + new[key] = value + return new + + +def maybe_filter_request_body( + data: typing.Optional[typing.Any], + request_options: typing.Optional[RequestOptions], + omit: typing.Optional[typing.Any], +) -> typing.Optional[typing.Any]: + if data is None: + return ( + jsonable_encoder(request_options.get("additional_body_parameters", {})) + if request_options is not None + else None + ) + elif not isinstance(data, typing.Mapping): + data_content = jsonable_encoder(data) + else: + data_content = { + **(jsonable_encoder(remove_omit_from_dict(data, omit))), # type: ignore + **( + jsonable_encoder(request_options.get("additional_body_parameters", {})) + if request_options is not None + else {} + ), + } + return data_content + + +# Abstracted out for testing purposes +def get_request_body( + *, + json: typing.Optional[typing.Any], + data: typing.Optional[typing.Any], + request_options: typing.Optional[RequestOptions], + omit: typing.Optional[typing.Any], +) -> typing.Tuple[typing.Optional[typing.Any], typing.Optional[typing.Any]]: + json_body = None + data_body = None + if data is not None: + data_body = maybe_filter_request_body(data, request_options, omit) + else: + # If both data and json are None, we send json data in the event extra properties are specified + json_body = maybe_filter_request_body(json, request_options, omit) + + return json_body, data_body + + +class HttpClient: + def __init__( + self, + *, + httpx_client: httpx.Client, + base_timeout: typing.Optional[float], + base_headers: typing.Dict[str, str], + base_url: typing.Optional[str] = None, + ): + self.base_url = base_url + self.base_timeout = base_timeout + self.base_headers = base_headers + self.httpx_client = httpx_client + + def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str: + base_url = self.base_url if maybe_base_url is None else maybe_base_url + if base_url is None: + raise ValueError("A base_url is required to make this request, please provide one and try again.") + return base_url + + def request( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 0, + omit: typing.Optional[typing.Any] = None, + ) -> httpx.Response: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout + ) + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + response = self.httpx_client.request( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers, + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) + if request_options is not None + else {} + ), + }, + omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=convert_file_dict_to_httpx_tuples(remove_none_from_dict(files)) if files is not None else None, + timeout=timeout, + ) + + max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0 + if _should_retry(response=response): + if max_retries > retries: + time.sleep(_retry_timeout(response=response, retries=retries)) + return self.request( + path=path, + method=method, + base_url=base_url, + params=params, + json=json, + content=content, + files=files, + headers=headers, + request_options=request_options, + retries=retries + 1, + omit=omit, + ) + + return response + + @contextmanager + def stream( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 0, + omit: typing.Optional[typing.Any] = None, + ) -> typing.Iterator[httpx.Response]: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout + ) + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + with self.httpx_client.stream( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers, + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) + if request_options is not None + else {} + ), + }, + omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=convert_file_dict_to_httpx_tuples(remove_none_from_dict(files)) if files is not None else None, + timeout=timeout, + ) as stream: + yield stream + + +class AsyncHttpClient: + def __init__( + self, + *, + httpx_client: httpx.AsyncClient, + base_timeout: typing.Optional[float], + base_headers: typing.Dict[str, str], + base_url: typing.Optional[str] = None, + ): + self.base_url = base_url + self.base_timeout = base_timeout + self.base_headers = base_headers + self.httpx_client = httpx_client + + def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str: + base_url = self.base_url if maybe_base_url is None else maybe_base_url + if base_url is None: + raise ValueError("A base_url is required to make this request, please provide one and try again.") + return base_url + + async def request( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 0, + omit: typing.Optional[typing.Any] = None, + ) -> httpx.Response: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout + ) + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + # Add the input to each of these and do None-safety checks + response = await self.httpx_client.request( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers, + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) + if request_options is not None + else {} + ), + }, + omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=convert_file_dict_to_httpx_tuples(remove_none_from_dict(files)) if files is not None else None, + timeout=timeout, + ) + + max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0 + if _should_retry(response=response): + if max_retries > retries: + await asyncio.sleep(_retry_timeout(response=response, retries=retries)) + return await self.request( + path=path, + method=method, + base_url=base_url, + params=params, + json=json, + content=content, + files=files, + headers=headers, + request_options=request_options, + retries=retries + 1, + omit=omit, + ) + return response + + @asynccontextmanager + async def stream( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 0, + omit: typing.Optional[typing.Any] = None, + ) -> typing.AsyncIterator[httpx.Response]: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout + ) + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + async with self.httpx_client.stream( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers, + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) + if request_options is not None + else {} + ), + }, + omit=omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=convert_file_dict_to_httpx_tuples(remove_none_from_dict(files)) if files is not None else None, + timeout=timeout, + ) as stream: + yield stream diff --git a/src/webflow/core/jsonable_encoder.py b/src/webflow/core/jsonable_encoder.py index 37238ab..7f48273 100644 --- a/src/webflow/core/jsonable_encoder.py +++ b/src/webflow/core/jsonable_encoder.py @@ -16,12 +16,8 @@ from types import GeneratorType from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - from .datetime_utils import serialize_datetime +from .pydantic_utilities import pydantic_v1 SetIntStr = Set[Union[int, str]] DictIntStrAny = Dict[Union[int, str], Any] @@ -36,7 +32,7 @@ def generate_encoders_by_class_tuples( return encoders_by_class_tuples -encoders_by_class_tuples = generate_encoders_by_class_tuples(pydantic.json.ENCODERS_BY_TYPE) +encoders_by_class_tuples = generate_encoders_by_class_tuples(pydantic_v1.json.ENCODERS_BY_TYPE) def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None) -> Any: @@ -48,7 +44,7 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any] for encoder_type, encoder_instance in custom_encoder.items(): if isinstance(obj, encoder_type): return encoder_instance(obj) - if isinstance(obj, pydantic.BaseModel): + if isinstance(obj, pydantic_v1.BaseModel): encoder = getattr(obj.__config__, "json_encoders", {}) if custom_encoder: encoder.update(custom_encoder) @@ -65,10 +61,10 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any] return str(obj) if isinstance(obj, (str, int, float, type(None))): return obj - if isinstance(obj, dt.date): - return str(obj) if isinstance(obj, dt.datetime): return serialize_datetime(obj) + if isinstance(obj, dt.date): + return str(obj) if isinstance(obj, dict): encoded_dict = {} allowed_keys = set(obj.keys()) @@ -84,8 +80,8 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any] encoded_list.append(jsonable_encoder(item, custom_encoder=custom_encoder)) return encoded_list - if type(obj) in pydantic.json.ENCODERS_BY_TYPE: - return pydantic.json.ENCODERS_BY_TYPE[type(obj)](obj) + if type(obj) in pydantic_v1.json.ENCODERS_BY_TYPE: + return pydantic_v1.json.ENCODERS_BY_TYPE[type(obj)](obj) for encoder, classes_tuple in encoders_by_class_tuples.items(): if isinstance(obj, classes_tuple): return encoder(obj) diff --git a/src/webflow/core/pydantic_utilities.py b/src/webflow/core/pydantic_utilities.py new file mode 100644 index 0000000..a72c1a5 --- /dev/null +++ b/src/webflow/core/pydantic_utilities.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic + +IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.") + +if IS_PYDANTIC_V2: + import pydantic.v1 as pydantic_v1 # type: ignore # nopycln: import +else: + import pydantic as pydantic_v1 # type: ignore # nopycln: import + + +def deep_union_pydantic_dicts( + source: typing.Dict[str, typing.Any], destination: typing.Dict[str, typing.Any] +) -> typing.Dict[str, typing.Any]: + for key, value in source.items(): + if isinstance(value, dict): + node = destination.setdefault(key, {}) + deep_union_pydantic_dicts(value, node) + else: + destination[key] = value + + return destination + + +__all__ = ["pydantic_v1"] diff --git a/src/webflow/core/query_encoder.py b/src/webflow/core/query_encoder.py new file mode 100644 index 0000000..1f5f766 --- /dev/null +++ b/src/webflow/core/query_encoder.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from collections import ChainMap +from typing import Any, Dict, Optional + +from .pydantic_utilities import pydantic_v1 + + +# Flattens dicts to be of the form {"key[subkey][subkey2]": value} where value is not a dict +def traverse_query_dict(dict_flat: Dict[str, Any], key_prefix: Optional[str] = None) -> Dict[str, Any]: + result = {} + for k, v in dict_flat.items(): + key = f"{key_prefix}[{k}]" if key_prefix is not None else k + if isinstance(v, dict): + result.update(traverse_query_dict(v, key)) + else: + result[key] = v + return result + + +def single_query_encoder(query_key: str, query_value: Any) -> Dict[str, Any]: + if isinstance(query_value, pydantic_v1.BaseModel) or isinstance(query_value, dict): + if isinstance(query_value, pydantic_v1.BaseModel): + obj_dict = query_value.dict(by_alias=True) + else: + obj_dict = query_value + return traverse_query_dict(obj_dict, query_key) + + return {query_key: query_value} + + +def encode_query(query: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]: + return dict(ChainMap(*[single_query_encoder(k, v) for k, v in query.items()])) if query is not None else None diff --git a/src/webflow/core/remove_none_from_dict.py b/src/webflow/core/remove_none_from_dict.py index 2da30f7..c229814 100644 --- a/src/webflow/core/remove_none_from_dict.py +++ b/src/webflow/core/remove_none_from_dict.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from typing import Any, Dict, Optional +from typing import Any, Dict, Mapping, Optional -def remove_none_from_dict(original: Dict[str, Optional[Any]]) -> Dict[str, Any]: +def remove_none_from_dict(original: Mapping[str, Optional[Any]]) -> Dict[str, Any]: new: Dict[str, Any] = {} for key, value in original.items(): if value is not None: diff --git a/src/webflow/core/request_options.py b/src/webflow/core/request_options.py index 32e86b0..d0bf0db 100644 --- a/src/webflow/core/request_options.py +++ b/src/webflow/core/request_options.py @@ -5,10 +5,10 @@ try: from typing import NotRequired # type: ignore except ImportError: - from typing_extensions import NotRequired # type: ignore + from typing_extensions import NotRequired -class RequestOptions(typing.TypedDict): +class RequestOptions(typing.TypedDict, total=False): """ Additional options for request-specific configuration when calling APIs via the SDK. This is used primarily as an optional final parameter for service functions. @@ -16,6 +16,8 @@ class RequestOptions(typing.TypedDict): Attributes: - timeout_in_seconds: int. The number of seconds to await an API call before timing out. + - max_retries: int. The max number of retries to attempt if the API call fails. + - additional_headers: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's header dict - additional_query_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's query parameters dict @@ -24,6 +26,7 @@ class RequestOptions(typing.TypedDict): """ timeout_in_seconds: NotRequired[int] + max_retries: NotRequired[int] additional_headers: NotRequired[typing.Dict[str, typing.Any]] additional_query_parameters: NotRequired[typing.Dict[str, typing.Any]] additional_body_parameters: NotRequired[typing.Dict[str, typing.Any]] diff --git a/src/webflow/resources/__init__.py b/src/webflow/resources/__init__.py index b2501ad..91d1d63 100644 --- a/src/webflow/resources/__init__.py +++ b/src/webflow/resources/__init__.py @@ -18,41 +18,19 @@ ) from .access_groups import AccessGroupsListRequestSort from .inventory import InventoryUpdateRequestInventoryType -from .orders import OrdersRefundRequestReason -from .pages import DomWriteNodesItem -from .products import ( - ProductSkuCreateProduct, - ProductSkuCreateProductFieldData, - ProductSkuCreateProductFieldDataEcProductType, - ProductSkuCreateProductFieldDataTaxCategory, - ProductSkuCreateSku, - ProductSkuCreateSkuFieldData, - ProductSkuCreateSkuFieldDataCompareAtPrice, - ProductSkuCreateSkuFieldDataEcSkuBillingMethod, - ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlan, - ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval, - ProductSkuCreateSkuFieldDataPrice, - ProductsCreateSkuResponse, -) +from .orders import OrdersListRequestStatus, OrdersRefundRequestReason +from .pages import DomWriteNodesItem, UpdateStaticContentResponse +from .products import ProductsCreateSkuResponse from .users import UsersListRequestSort, UsersUpdateRequestData __all__ = [ "AccessGroupsListRequestSort", "DomWriteNodesItem", "InventoryUpdateRequestInventoryType", + "OrdersListRequestStatus", "OrdersRefundRequestReason", - "ProductSkuCreateProduct", - "ProductSkuCreateProductFieldData", - "ProductSkuCreateProductFieldDataEcProductType", - "ProductSkuCreateProductFieldDataTaxCategory", - "ProductSkuCreateSku", - "ProductSkuCreateSkuFieldData", - "ProductSkuCreateSkuFieldDataCompareAtPrice", - "ProductSkuCreateSkuFieldDataEcSkuBillingMethod", - "ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlan", - "ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval", - "ProductSkuCreateSkuFieldDataPrice", "ProductsCreateSkuResponse", + "UpdateStaticContentResponse", "UsersListRequestSort", "UsersUpdateRequestData", "access_groups", diff --git a/src/webflow/resources/access_groups/client.py b/src/webflow/resources/access_groups/client.py index bfd306e..2f0e14f 100644 --- a/src/webflow/resources/access_groups/client.py +++ b/src/webflow/resources/access_groups/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError @@ -18,11 +17,6 @@ from ...types.access_group_list import AccessGroupList from .types.access_groups_list_request_sort import AccessGroupsListRequestSort -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - class AccessGroupsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): @@ -40,17 +34,31 @@ def list( """ Get a list of access groups for a site

Required scope | `users:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + sort : typing.Optional[AccessGroupsListRequestSort] + Sort string to use when ordering access groups + Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + Returns + ------- + AccessGroupList + Request was successful - - sort: typing.Optional[AccessGroupsListRequestSort]. Sort string to use when ordering access groups - Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -61,51 +69,26 @@ def list( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/accessgroups" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "offset": offset, - "limit": limit, - "sort": sort, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/accessgroups", + method="GET", + params={"offset": offset, "limit": limit, "sort": sort}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AccessGroupList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AccessGroupList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -128,17 +111,31 @@ async def list( """ Get a list of access groups for a site

Required scope | `users:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + sort : typing.Optional[AccessGroupsListRequestSort] + Sort string to use when ordering access groups + Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + Returns + ------- + AccessGroupList + Request was successful - - sort: typing.Optional[AccessGroupsListRequestSort]. Sort string to use when ordering access groups - Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -149,51 +146,26 @@ async def list( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/accessgroups" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "offset": offset, - "limit": limit, - "sort": sort, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/accessgroups", + method="GET", + params={"offset": offset, "limit": limit, "sort": sort}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AccessGroupList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AccessGroupList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/assets/client.py b/src/webflow/resources/assets/client.py index 7be5754..131d573 100644 --- a/src/webflow/resources/assets/client.py +++ b/src/webflow/resources/assets/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.internal_server_error import InternalServerError @@ -20,11 +19,6 @@ from ...types.asset_upload import AssetUpload from ...types.assets import Assets -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -37,11 +31,21 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ List assets for a given site

Required scope | `assets:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Assets + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -52,38 +56,21 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/assets" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/assets", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Assets, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Assets, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -101,17 +88,30 @@ def create( """ Create a new asset entry.

This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) request to the `uploadUrl` with the `uploadDetails` object as your header information in the request.

Required scope | `assets:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_name : str + file name including file extension + + file_hash : str + MD5 hash of the file - - file_name: str. file name including file extension + parent_folder : typing.Optional[str] + id of the Asset folder (optional) - - file_hash: str. MD5 hash of the file + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - parent_folder: typing.Optional[str]. id of the Asset folder (optional) + Returns + ------- + AssetUpload + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -121,51 +121,28 @@ def create( site_id="site_id", file_name="file.png", file_hash="3c7d87c9575702bc3b1e991f4d3c638e", - parent_folder="6436b1ce5281cace05b65aea", ) """ - _request: typing.Dict[str, typing.Any] = {"fileName": file_name, "fileHash": file_hash} - if parent_folder is not OMIT: - _request["parentFolder"] = parent_folder _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/assets" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/assets", + method="POST", + json={"fileName": file_name, "fileHash": file_hash, "parentFolder": parent_folder}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AssetUpload, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AssetUpload, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -175,11 +152,21 @@ def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] """ Get an Asset

Required scope | `assets:read` - Parameters: - - asset_id: str. Unique identifier for an Asset on a site + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Asset + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -190,36 +177,21 @@ def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"assets/{jsonable_encoder(asset_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"assets/{jsonable_encoder(asset_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Asset, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Asset, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -229,11 +201,20 @@ def delete(self, asset_id: str, *, request_options: typing.Optional[RequestOptio """ Delete an Asset - Parameters: - - asset_id: str. Unique identifier for an Asset on a site + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -244,36 +225,21 @@ def delete(self, asset_id: str, *, request_options: typing.Optional[RequestOptio ) """ _response = self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"assets/{jsonable_encoder(asset_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"assets/{jsonable_encoder(asset_id)}", method="DELETE", request_options=request_options ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -285,13 +251,24 @@ def update( """ Update an Asset

Required scope | `assets:write` - Parameters: - - asset_id: str. Unique identifier for an Asset on a site + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site - - display_name: str. file name including file extension + display_name : str + file name including file extension - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Asset + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -303,42 +280,25 @@ def update( ) """ _response = self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"assets/{jsonable_encoder(asset_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder({"displayName": display_name}) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder({"displayName": display_name}), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"assets/{jsonable_encoder(asset_id)}", + method="PATCH", + json={"displayName": display_name}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Asset, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Asset, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -348,11 +308,21 @@ def list_folders(self, site_id: str, *, request_options: typing.Optional[Request """ List Asset Folders within a given site

Required scope | `assets:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AssetFolderList + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -363,38 +333,21 @@ def list_folders(self, site_id: str, *, request_options: typing.Optional[Request ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/asset_folders" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/asset_folders", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AssetFolderList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AssetFolderList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -411,15 +364,27 @@ def create_folder( """ Create an Asset Folder within a given site

Required scope | `assets:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - display_name: str. A human readable name for the Asset Folder + display_name : str + A human readable name for the Asset Folder - - parent_folder: typing.Optional[str]. An (optional) pointer to a parent Asset Folder (or null for root) + parent_folder : typing.Optional[str] + An (optional) pointer to a parent Asset Folder (or null for root) - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AssetFolder + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -428,51 +393,28 @@ def create_folder( client.assets.create_folder( site_id="site_id", display_name="my asset folder", - parent_folder="6390c49774a71f99f21a08eb", ) """ - _request: typing.Dict[str, typing.Any] = {"displayName": display_name} - if parent_folder is not OMIT: - _request["parentFolder"] = parent_folder _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/asset_folders" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/asset_folders", + method="POST", + json={"displayName": display_name, "parentFolder": parent_folder}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AssetFolder, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AssetFolder, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -484,11 +426,21 @@ def get_folder( """ Get details about a specific Asset Folder

Required scope | `assets:read` - Parameters: - - asset_folder_id: str. Unique identifier for an Asset Folder + Parameters + ---------- + asset_folder_id : str + Unique identifier for an Asset Folder + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AssetFolder + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -499,38 +451,21 @@ def get_folder( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"asset_folders/{jsonable_encoder(asset_folder_id)}" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"asset_folders/{jsonable_encoder(asset_folder_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AssetFolder, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AssetFolder, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -545,11 +480,21 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp """ List assets for a given site

Required scope | `assets:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Assets + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -560,38 +505,21 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/assets" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/assets", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Assets, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Assets, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -609,17 +537,30 @@ async def create( """ Create a new asset entry.

This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) request to the `uploadUrl` with the `uploadDetails` object as your header information in the request.

Required scope | `assets:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_name : str + file name including file extension + + file_hash : str + MD5 hash of the file - - file_name: str. file name including file extension + parent_folder : typing.Optional[str] + id of the Asset folder (optional) - - file_hash: str. MD5 hash of the file + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - parent_folder: typing.Optional[str]. id of the Asset folder (optional) + Returns + ------- + AssetUpload + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -629,51 +570,28 @@ async def create( site_id="site_id", file_name="file.png", file_hash="3c7d87c9575702bc3b1e991f4d3c638e", - parent_folder="6436b1ce5281cace05b65aea", ) """ - _request: typing.Dict[str, typing.Any] = {"fileName": file_name, "fileHash": file_hash} - if parent_folder is not OMIT: - _request["parentFolder"] = parent_folder _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/assets" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/assets", + method="POST", + json={"fileName": file_name, "fileHash": file_hash, "parentFolder": parent_folder}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AssetUpload, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AssetUpload, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -683,11 +601,21 @@ async def get(self, asset_id: str, *, request_options: typing.Optional[RequestOp """ Get an Asset

Required scope | `assets:read` - Parameters: - - asset_id: str. Unique identifier for an Asset on a site + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Asset + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -698,36 +626,21 @@ async def get(self, asset_id: str, *, request_options: typing.Optional[RequestOp ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"assets/{jsonable_encoder(asset_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"assets/{jsonable_encoder(asset_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Asset, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Asset, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -737,11 +650,20 @@ async def delete(self, asset_id: str, *, request_options: typing.Optional[Reques """ Delete an Asset - Parameters: - - asset_id: str. Unique identifier for an Asset on a site + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -752,36 +674,21 @@ async def delete(self, asset_id: str, *, request_options: typing.Optional[Reques ) """ _response = await self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"assets/{jsonable_encoder(asset_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"assets/{jsonable_encoder(asset_id)}", method="DELETE", request_options=request_options ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -793,13 +700,24 @@ async def update( """ Update an Asset

Required scope | `assets:write` - Parameters: - - asset_id: str. Unique identifier for an Asset on a site + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site - - display_name: str. file name including file extension + display_name : str + file name including file extension - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Asset + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -811,42 +729,25 @@ async def update( ) """ _response = await self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"assets/{jsonable_encoder(asset_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder({"displayName": display_name}) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder({"displayName": display_name}), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"assets/{jsonable_encoder(asset_id)}", + method="PATCH", + json={"displayName": display_name}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Asset, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Asset, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -858,11 +759,21 @@ async def list_folders( """ List Asset Folders within a given site

Required scope | `assets:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AssetFolderList + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -873,38 +784,21 @@ async def list_folders( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/asset_folders" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/asset_folders", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AssetFolderList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AssetFolderList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -921,15 +815,27 @@ async def create_folder( """ Create an Asset Folder within a given site

Required scope | `assets:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - display_name: str. A human readable name for the Asset Folder + display_name : str + A human readable name for the Asset Folder - - parent_folder: typing.Optional[str]. An (optional) pointer to a parent Asset Folder (or null for root) + parent_folder : typing.Optional[str] + An (optional) pointer to a parent Asset Folder (or null for root) - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AssetFolder + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -938,51 +844,28 @@ async def create_folder( await client.assets.create_folder( site_id="site_id", display_name="my asset folder", - parent_folder="6390c49774a71f99f21a08eb", ) """ - _request: typing.Dict[str, typing.Any] = {"displayName": display_name} - if parent_folder is not OMIT: - _request["parentFolder"] = parent_folder _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/asset_folders" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/asset_folders", + method="POST", + json={"displayName": display_name, "parentFolder": parent_folder}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AssetFolder, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AssetFolder, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -994,11 +877,21 @@ async def get_folder( """ Get details about a specific Asset Folder

Required scope | `assets:read` - Parameters: - - asset_folder_id: str. Unique identifier for an Asset Folder + Parameters + ---------- + asset_folder_id : str + Unique identifier for an Asset Folder + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AssetFolder + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -1009,38 +902,21 @@ async def get_folder( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"asset_folders/{jsonable_encoder(asset_folder_id)}" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"asset_folders/{jsonable_encoder(asset_folder_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AssetFolder, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AssetFolder, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/collections/__init__.py b/src/webflow/resources/collections/__init__.py index ea60c9c..a029bd0 100644 --- a/src/webflow/resources/collections/__init__.py +++ b/src/webflow/resources/collections/__init__.py @@ -1,5 +1,23 @@ # This file was auto-generated by Fern from our API Definition. -from .resources import BulkCollectionItemFieldData, FieldCreateType, ItemsPublishItemResponse, fields, items +from .resources import ( + BulkCollectionItemFieldData, + FieldCreateType, + ItemsListItemsLiveRequestSortBy, + ItemsListItemsLiveRequestSortOrder, + ItemsListItemsRequestSortBy, + ItemsListItemsRequestSortOrder, + fields, + items, +) -__all__ = ["BulkCollectionItemFieldData", "FieldCreateType", "ItemsPublishItemResponse", "fields", "items"] +__all__ = [ + "BulkCollectionItemFieldData", + "FieldCreateType", + "ItemsListItemsLiveRequestSortBy", + "ItemsListItemsLiveRequestSortOrder", + "ItemsListItemsRequestSortBy", + "ItemsListItemsRequestSortOrder", + "fields", + "items", +] diff --git a/src/webflow/resources/collections/client.py b/src/webflow/resources/collections/client.py index 669cb06..1d1ba20 100644 --- a/src/webflow/resources/collections/client.py +++ b/src/webflow/resources/collections/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.internal_server_error import InternalServerError @@ -19,11 +18,6 @@ from .resources.fields.client import AsyncFieldsClient, FieldsClient from .resources.items.client import AsyncItemsClient, ItemsClient -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -38,11 +32,21 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ List of all Collections within a Site.

Required scope | `cms:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionList + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -53,38 +57,21 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/collections" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/collections", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CollectionList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -102,17 +89,30 @@ def create( """ Create a Collection for a site.

Required scope | `cms:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - display_name: str. Name of the collection. Each collection name must be distinct. + display_name : str + Name of the collection. Each collection name must be distinct. - - singular_name: str. Singular name of each item. + singular_name : str + Singular name of each item. - - slug: typing.Optional[str]. Part of a URL that identifier + slug : typing.Optional[str] + Part of a URL that identifier - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Collection + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -125,48 +125,26 @@ def create( slug="posts", ) """ - _request: typing.Dict[str, typing.Any] = {"displayName": display_name, "singularName": singular_name} - if slug is not OMIT: - _request["slug"] = slug _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/collections" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/collections", + method="POST", + json={"displayName": display_name, "singularName": singular_name, "slug": slug}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Collection, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Collection, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -176,11 +154,21 @@ def get(self, collection_id: str, *, request_options: typing.Optional[RequestOpt """ Get the full details of a collection from its ID.

Required scope | `cms:read` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Collection + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -191,38 +179,21 @@ def get(self, collection_id: str, *, request_options: typing.Optional[RequestOpt ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Collection, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Collection, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -232,11 +203,20 @@ def delete_collection(self, collection_id: str, *, request_options: typing.Optio """ Delete a collection using its ID.

Required scope | `cms:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -247,38 +227,21 @@ def delete_collection(self, collection_id: str, *, request_options: typing.Optio ) """ _response = self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}", method="DELETE", request_options=request_options ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -290,13 +253,23 @@ def delete( """ Delete a custom field in a collection. This endpoint does not currently support bulk deletion.

Required scope | `cms:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_id : str + Unique identifier for a Field in a collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - field_id: str. Unique identifier for a Field in a collection + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -308,39 +281,23 @@ def delete( ) """ _response = self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + method="DELETE", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -357,11 +314,21 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp """ List of all Collections within a Site.

Required scope | `cms:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionList + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -372,38 +339,21 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/collections" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/collections", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CollectionList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -421,17 +371,30 @@ async def create( """ Create a Collection for a site.

Required scope | `cms:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + display_name : str + Name of the collection. Each collection name must be distinct. - - display_name: str. Name of the collection. Each collection name must be distinct. + singular_name : str + Singular name of each item. - - singular_name: str. Singular name of each item. + slug : typing.Optional[str] + Part of a URL that identifier - - slug: typing.Optional[str]. Part of a URL that identifier + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Collection + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -444,48 +407,26 @@ async def create( slug="posts", ) """ - _request: typing.Dict[str, typing.Any] = {"displayName": display_name, "singularName": singular_name} - if slug is not OMIT: - _request["slug"] = slug _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/collections" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/collections", + method="POST", + json={"displayName": display_name, "singularName": singular_name, "slug": slug}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Collection, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Collection, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -495,11 +436,21 @@ async def get(self, collection_id: str, *, request_options: typing.Optional[Requ """ Get the full details of a collection from its ID.

Required scope | `cms:read` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Collection + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -510,38 +461,21 @@ async def get(self, collection_id: str, *, request_options: typing.Optional[Requ ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Collection, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Collection, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -553,11 +487,20 @@ async def delete_collection( """ Delete a collection using its ID.

Required scope | `cms:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -568,38 +511,21 @@ async def delete_collection( ) """ _response = await self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}", method="DELETE", request_options=request_options ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -611,13 +537,23 @@ async def delete( """ Delete a custom field in a collection. This endpoint does not currently support bulk deletion.

Required scope | `cms:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_id : str + Unique identifier for a Field in a collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - field_id: str. Unique identifier for a Field in a collection + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -629,39 +565,23 @@ async def delete( ) """ _response = await self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + method="DELETE", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/collections/resources/__init__.py b/src/webflow/resources/collections/resources/__init__.py index 5b63931..2b2d370 100644 --- a/src/webflow/resources/collections/resources/__init__.py +++ b/src/webflow/resources/collections/resources/__init__.py @@ -2,6 +2,21 @@ from . import fields, items from .fields import FieldCreateType -from .items import BulkCollectionItemFieldData, ItemsPublishItemResponse +from .items import ( + BulkCollectionItemFieldData, + ItemsListItemsLiveRequestSortBy, + ItemsListItemsLiveRequestSortOrder, + ItemsListItemsRequestSortBy, + ItemsListItemsRequestSortOrder, +) -__all__ = ["BulkCollectionItemFieldData", "FieldCreateType", "ItemsPublishItemResponse", "fields", "items"] +__all__ = [ + "BulkCollectionItemFieldData", + "FieldCreateType", + "ItemsListItemsLiveRequestSortBy", + "ItemsListItemsLiveRequestSortOrder", + "ItemsListItemsRequestSortBy", + "ItemsListItemsRequestSortOrder", + "fields", + "items", +] diff --git a/src/webflow/resources/collections/resources/fields/client.py b/src/webflow/resources/collections/resources/fields/client.py index 9622f64..710092f 100644 --- a/src/webflow/resources/collections/resources/fields/client.py +++ b/src/webflow/resources/collections/resources/fields/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from .....core.api_error import ApiError from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.jsonable_encoder import jsonable_encoder -from .....core.remove_none_from_dict import remove_none_from_dict +from .....core.pydantic_utilities import pydantic_v1 from .....core.request_options import RequestOptions from .....errors.bad_request_error import BadRequestError from .....errors.internal_server_error import InternalServerError @@ -17,11 +16,6 @@ from .....types.field import Field from .types.field_create_type import FieldCreateType -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -34,28 +28,42 @@ def create( self, collection_id: str, *, - is_required: typing.Optional[bool] = OMIT, type: FieldCreateType, display_name: str, + is_required: typing.Optional[bool] = OMIT, help_text: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Field: """ Create a custom field in a collection.

Slugs must be all lowercase letters without spaces. If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will convert the slug to lowercase and replace spaces with "-."

Only some field types can be created through the API. This endpoint does not currently support bulk creation.

Required scope | `cms:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + type : FieldCreateType + Choose these appropriate field type for your collection data - - is_required: typing.Optional[bool]. define whether a field is required in a collection + display_name : str + The name of a field - - type: FieldCreateType. Choose these appropriate field type for your collection data + is_required : typing.Optional[bool] + define whether a field is required in a collection - - display_name: str. The name of a field + help_text : typing.Optional[str] + Additional text to help anyone filling out this field - - help_text: typing.Optional[str]. Additional text to help anyone filling out this field + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Field + Request was successful + + Examples + -------- from webflow.client import Webflow from webflow.resources.collections import FieldCreateType @@ -70,50 +78,26 @@ def create( help_text="Add the body of your post here", ) """ - _request: typing.Dict[str, typing.Any] = {"type": type, "displayName": display_name} - if is_required is not OMIT: - _request["isRequired"] = is_required - if help_text is not OMIT: - _request["helpText"] = help_text _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}/fields" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}/fields", + method="POST", + json={"isRequired": is_required, "type": type, "displayName": display_name, "helpText": help_text}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Field, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Field, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -132,19 +116,33 @@ def update( """ Update a custom field in a collection.

Required scope | `cms:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_id : str + Unique identifier for a Field in a collection + + is_required : typing.Optional[bool] + Define whether a field is required in a collection - - field_id: str. Unique identifier for a Field in a collection + display_name : typing.Optional[str] + The name of a field - - is_required: typing.Optional[bool]. Define whether a field is required in a collection + help_text : typing.Optional[str] + Additional text to help anyone filling out this field - - display_name: typing.Optional[str]. The name of a field + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - help_text: typing.Optional[str]. Additional text to help anyone filling out this field + Returns + ------- + Field + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -158,53 +156,26 @@ def update( help_text="Add the body of your post here", ) """ - _request: typing.Dict[str, typing.Any] = {} - if is_required is not OMIT: - _request["isRequired"] = is_required - if display_name is not OMIT: - _request["displayName"] = display_name - if help_text is not OMIT: - _request["helpText"] = help_text _response = self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + method="PATCH", + json={"isRequired": is_required, "displayName": display_name, "helpText": help_text}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Field, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Field, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -219,28 +190,42 @@ async def create( self, collection_id: str, *, - is_required: typing.Optional[bool] = OMIT, type: FieldCreateType, display_name: str, + is_required: typing.Optional[bool] = OMIT, help_text: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Field: """ Create a custom field in a collection.

Slugs must be all lowercase letters without spaces. If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will convert the slug to lowercase and replace spaces with "-."

Only some field types can be created through the API. This endpoint does not currently support bulk creation.

Required scope | `cms:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + type : FieldCreateType + Choose these appropriate field type for your collection data - - is_required: typing.Optional[bool]. define whether a field is required in a collection + display_name : str + The name of a field - - type: FieldCreateType. Choose these appropriate field type for your collection data + is_required : typing.Optional[bool] + define whether a field is required in a collection - - display_name: str. The name of a field + help_text : typing.Optional[str] + Additional text to help anyone filling out this field - - help_text: typing.Optional[str]. Additional text to help anyone filling out this field + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Field + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow from webflow.resources.collections import FieldCreateType @@ -255,50 +240,26 @@ async def create( help_text="Add the body of your post here", ) """ - _request: typing.Dict[str, typing.Any] = {"type": type, "displayName": display_name} - if is_required is not OMIT: - _request["isRequired"] = is_required - if help_text is not OMIT: - _request["helpText"] = help_text _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}/fields" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}/fields", + method="POST", + json={"isRequired": is_required, "type": type, "displayName": display_name, "helpText": help_text}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Field, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Field, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -317,19 +278,33 @@ async def update( """ Update a custom field in a collection.

Required scope | `cms:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_id : str + Unique identifier for a Field in a collection + + is_required : typing.Optional[bool] + Define whether a field is required in a collection - - field_id: str. Unique identifier for a Field in a collection + display_name : typing.Optional[str] + The name of a field - - is_required: typing.Optional[bool]. Define whether a field is required in a collection + help_text : typing.Optional[str] + Additional text to help anyone filling out this field - - display_name: typing.Optional[str]. The name of a field + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - help_text: typing.Optional[str]. Additional text to help anyone filling out this field + Returns + ------- + Field + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -343,53 +318,26 @@ async def update( help_text="Add the body of your post here", ) """ - _request: typing.Dict[str, typing.Any] = {} - if is_required is not OMIT: - _request["isRequired"] = is_required - if display_name is not OMIT: - _request["displayName"] = display_name - if help_text is not OMIT: - _request["helpText"] = help_text _response = await self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + method="PATCH", + json={"isRequired": is_required, "displayName": display_name, "helpText": help_text}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Field, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Field, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/collections/resources/fields/types/field_create_type.py b/src/webflow/resources/collections/resources/fields/types/field_create_type.py index db7db4a..adf2907 100644 --- a/src/webflow/resources/collections/resources/fields/types/field_create_type.py +++ b/src/webflow/resources/collections/resources/fields/types/field_create_type.py @@ -21,7 +21,7 @@ class FieldCreateType(str, enum.Enum): PHONE = "Phone" NUMBER = "Number" DATE_TIME = "DateTime" - BOOLEAN = "Boolean" + SWITCH = "Switch" COLOR = "Color" FILE = "File" @@ -37,7 +37,7 @@ def visit( phone: typing.Callable[[], T_Result], number: typing.Callable[[], T_Result], date_time: typing.Callable[[], T_Result], - boolean: typing.Callable[[], T_Result], + switch: typing.Callable[[], T_Result], color: typing.Callable[[], T_Result], file: typing.Callable[[], T_Result], ) -> T_Result: @@ -61,8 +61,8 @@ def visit( return number() if self is FieldCreateType.DATE_TIME: return date_time() - if self is FieldCreateType.BOOLEAN: - return boolean() + if self is FieldCreateType.SWITCH: + return switch() if self is FieldCreateType.COLOR: return color() if self is FieldCreateType.FILE: diff --git a/src/webflow/resources/collections/resources/items/__init__.py b/src/webflow/resources/collections/resources/items/__init__.py index f9fc28c..c8549f0 100644 --- a/src/webflow/resources/collections/resources/items/__init__.py +++ b/src/webflow/resources/collections/resources/items/__init__.py @@ -1,5 +1,17 @@ # This file was auto-generated by Fern from our API Definition. -from .types import BulkCollectionItemFieldData, ItemsPublishItemResponse +from .types import ( + BulkCollectionItemFieldData, + ItemsListItemsLiveRequestSortBy, + ItemsListItemsLiveRequestSortOrder, + ItemsListItemsRequestSortBy, + ItemsListItemsRequestSortOrder, +) -__all__ = ["BulkCollectionItemFieldData", "ItemsPublishItemResponse"] +__all__ = [ + "BulkCollectionItemFieldData", + "ItemsListItemsLiveRequestSortBy", + "ItemsListItemsLiveRequestSortOrder", + "ItemsListItemsRequestSortBy", + "ItemsListItemsRequestSortOrder", +] diff --git a/src/webflow/resources/collections/resources/items/client.py b/src/webflow/resources/collections/resources/items/client.py index 21e4df3..9a51804 100644 --- a/src/webflow/resources/collections/resources/items/client.py +++ b/src/webflow/resources/collections/resources/items/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from .....core.api_error import ApiError from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.jsonable_encoder import jsonable_encoder -from .....core.remove_none_from_dict import remove_none_from_dict +from .....core.pydantic_utilities import pydantic_v1 from .....core.request_options import RequestOptions from .....errors.bad_request_error import BadRequestError from .....errors.internal_server_error import InternalServerError @@ -15,14 +14,13 @@ from .....errors.too_many_requests_error import TooManyRequestsError from .....errors.unauthorized_error import UnauthorizedError from .....types.collection_item import CollectionItem +from .....types.collection_item_field_data import CollectionItemFieldData from .....types.collection_item_list import CollectionItemList from .types.bulk_collection_item_field_data import BulkCollectionItemFieldData -from .types.items_publish_item_response import ItemsPublishItemResponse - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +from .types.items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy +from .types.items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder +from .types.items_list_items_request_sort_by import ItemsListItemsRequestSortBy +from .types.items_list_items_request_sort_order import ItemsListItemsRequestSortOrder # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -36,25 +34,54 @@ def list_items( self, collection_id: str, *, - cms_locale_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + cms_locale_id: typing.Optional[str] = None, offset: typing.Optional[float] = None, limit: typing.Optional[float] = None, + name: typing.Optional[str] = None, + slug: typing.Optional[str] = None, + sort_by: typing.Optional[ItemsListItemsRequestSortBy] = None, + sort_order: typing.Optional[ItemsListItemsRequestSortOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemList: """ List of all Items within a Collection.

Required scope | `CMS:read` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + name : typing.Optional[str] + The name of the item(s) + + slug : typing.Optional[str] + The slug of the item - - cms_locale_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]]. Unique identifiers for CMS Locales. These UIDs are different from the Site locale identifier and are listed as `cmsLocaleId` in the Sites response. Applicable when using localization. + sort_by : typing.Optional[ItemsListItemsRequestSortBy] + Sort results by the provided value - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + sort_order : typing.Optional[ItemsListItemsRequestSortOrder] + Sorts the results by asc or desc - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + CollectionItemList + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -65,68 +92,92 @@ def list_items( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}/items" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "cmsLocaleIds": cms_locale_ids, - "offset": offset, - "limit": limit, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CollectionItemList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + f"collections/{jsonable_encoder(collection_id)}/items", + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + "offset": offset, + "limit": limit, + "name": name, + "slug": slug, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItemList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) def create_item( - self, collection_id: str, *, request: CollectionItem, request_options: typing.Optional[RequestOptions] = None + self, + collection_id: str, + *, + id: str, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemFieldData] = OMIT, + request_options: typing.Optional[RequestOptions] = None, ) -> None: """ Create Item in a Collection.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + id : str + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published - - request: CollectionItem. + last_updated : typing.Optional[str] + The date the item was last updated - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import CollectionItem, CollectionItemFieldData + created_on : typing.Optional[str] + The date the item was created + + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived + + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft + + field_data : typing.Optional[CollectionItemFieldData] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from webflow import CollectionItemFieldData from webflow.client import Webflow client = Webflow( @@ -134,79 +185,201 @@ def create_item( ) client.collections.items.create_item( collection_id="collection_id", - request=CollectionItem( - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", ), ) """ _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}/items" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"collections/{jsonable_encoder(collection_id)}/items", + method="POST", + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": field_data, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + request_options=request_options, + omit=OMIT, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def list_items_live( + self, + collection_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + name: typing.Optional[str] = None, + slug: typing.Optional[str] = None, + sort_by: typing.Optional[ItemsListItemsLiveRequestSortBy] = None, + sort_order: typing.Optional[ItemsListItemsLiveRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CollectionItemList: + """ + List of all live Items within a Collection.

Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + name : typing.Optional[str] + The name of the item(s) + + slug : typing.Optional[str] + The slug of the item + + sort_by : typing.Optional[ItemsListItemsLiveRequestSortBy] + Sort results by the provided value + + sort_order : typing.Optional[ItemsListItemsLiveRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionItemList + Request was successful + + Examples + -------- + from webflow.client import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.collections.items.list_items_live( + collection_id="collection_id", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + "offset": offset, + "limit": limit, + "name": name, + "slug": slug, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItemList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) def create_item_live( - self, collection_id: str, *, request: CollectionItem, request_options: typing.Optional[RequestOptions] = None + self, + collection_id: str, + *, + id: str, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemFieldData] = OMIT, + request_options: typing.Optional[RequestOptions] = None, ) -> None: """ Create live Item in a Collection. This Item will be published to the live site.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + id : str + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published + + last_updated : typing.Optional[str] + The date the item was last updated + + created_on : typing.Optional[str] + The date the item was created + + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived + + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft + + field_data : typing.Optional[CollectionItemFieldData] - - request: CollectionItem. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import CollectionItem, CollectionItemFieldData + Returns + ------- + None + + Examples + -------- + from webflow import CollectionItemFieldData from webflow.client import Webflow client = Webflow( @@ -214,60 +387,48 @@ def create_item_live( ) client.collections.items.create_item_live( collection_id="collection_id", - request=CollectionItem( - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", ), ) """ _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}/items/live" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"collections/{jsonable_encoder(collection_id)}/items/live", + method="POST", + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": field_data, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + request_options=request_options, + omit=OMIT, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -290,29 +451,44 @@ def create_item_for_multiple_locales( """ Create single Item in a Collection with multiple corresponding locales.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + id : str + Unique identifier for the Item - - id: str. Unique identifier for the Item + cms_locale_ids : typing.Optional[typing.Sequence[str]] + Array of identifiers for the locales where the item will be created - - cms_locale_ids: typing.Optional[typing.Sequence[str]]. Array of identifiers for the locales where the item will be created + last_published : typing.Optional[str] + The date the item was last published - - last_published: typing.Optional[str]. The date the item was last published + last_updated : typing.Optional[str] + The date the item was last updated - - last_updated: typing.Optional[str]. The date the item was last updated + created_on : typing.Optional[str] + The date the item was created - - created_on: typing.Optional[str]. The date the item was created + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived - - is_archived: typing.Optional[bool]. Boolean determining if the Item is set to archived + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft - - is_draft: typing.Optional[bool]. Boolean determining if the Item is set to draft + field_data : typing.Optional[BulkCollectionItemFieldData] - - field_data: typing.Optional[BulkCollectionItemFieldData]. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + None + + Examples + -------- from webflow.client import Webflow - from webflow.resources.collections import BulkCollectionItemFieldData client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -320,69 +496,37 @@ def create_item_for_multiple_locales( client.collections.items.create_item_for_multiple_locales( collection_id="collection_id", id="580e64008c9a982ac9b8b754", - last_published="2023-03-17T18:47:35.560Z", - last_updated="2023-03-17T18:47:35.560Z", - created_on="2023-03-17T18:47:35.560Z", - field_data=BulkCollectionItemFieldData( - name="My new item", - slug="my-new-item", - ), ) """ - _request: typing.Dict[str, typing.Any] = {"id": id} - if cms_locale_ids is not OMIT: - _request["cmsLocaleIds"] = cms_locale_ids - if last_published is not OMIT: - _request["lastPublished"] = last_published - if last_updated is not OMIT: - _request["lastUpdated"] = last_updated - if created_on is not OMIT: - _request["createdOn"] = created_on - if is_archived is not OMIT: - _request["isArchived"] = is_archived - if is_draft is not OMIT: - _request["isDraft"] = is_draft - if field_data is not OMIT: - _request["fieldData"] = field_data _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}/items/bulk" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"collections/{jsonable_encoder(collection_id)}/items/bulk", + method="POST", + json={ + "id": id, + "cmsLocaleIds": cms_locale_ids, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": field_data, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + request_options=request_options, + omit=OMIT, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -399,15 +543,27 @@ def get_item( """ Get details of a selected Collection Item.

Required scope | `CMS:read` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection - - item_id: str. Unique identifier for an Item + item_id : str + Unique identifier for an Item - - cms_locale_id: typing.Optional[str]. Unique identifier for a CMS Locale. These UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. Applicable when using localization. + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionItem + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -419,48 +575,24 @@ def get_item( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "cmsLocaleId": cms_locale_id, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CollectionItem, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + method="GET", + params={"cmsLocaleId": cms_locale_id}, + request_options=request_options, + ) try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -471,21 +603,32 @@ def delete_item( collection_id: str, item_id: str, *, - cms_locale_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + cms_locale_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> None: """ Delete an Item from a Collection. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection - - item_id: str. Unique identifier for an Item + item_id : str + Unique identifier for an Item - - cms_locale_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]]. Unique identifiers for CMS Locales. These UIDs are different from the Site locale identifier and are listed as `cmsLocaleId` in the Sites response. Applicable when using localization. + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -497,48 +640,24 @@ def delete_item( ) """ _response = self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "cmsLocaleIds": cms_locale_ids, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + method="DELETE", + params={"cmsLocaleId": cms_locale_id}, + request_options=request_options, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -549,22 +668,61 @@ def update_item( collection_id: str, item_id: str, *, - request: CollectionItem, + id: str, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemFieldData] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ Update a selected Item in a Collection.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + id : str + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published + + last_updated : typing.Optional[str] + The date the item was last updated + + created_on : typing.Optional[str] + The date the item was created + + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived - - item_id: str. Unique identifier for an Item + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft - - request: CollectionItem. + field_data : typing.Optional[CollectionItemFieldData] - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import CollectionItem, CollectionItemFieldData + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionItem + Request was successful + + Examples + -------- + from webflow import CollectionItemFieldData from webflow.client import Webflow client = Webflow( @@ -573,79 +731,150 @@ def update_item( client.collections.items.update_item( collection_id="collection_id", item_id="item_id", - request=CollectionItem( - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", ), ) """ _response = self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + method="PATCH", + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": field_data, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CollectionItem, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + request_options=request_options, + omit=OMIT, + ) try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_item_live( + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CollectionItem: + """ + Get details of a selected Collection live Item.

Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionItem + Request was successful + + Examples + -------- + from webflow.client import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.collections.items.get_item_live( + collection_id="collection_id", + item_id="item_id", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + method="GET", + params={"cmsLocaleId": cms_locale_id}, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) def delete_item_live( - self, collection_id: str, item_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Delete a live Item from a Collection. The Item will be unpublished from the live site. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` + Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - Parameters: - - collection_id: str. Unique identifier for a Collection + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - item_id: str. Unique identifier for an Item + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -657,39 +886,24 @@ def delete_item_live( ) """ _response = self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + method="DELETE", + params={"cmsLocaleId": cms_locale_id}, + request_options=request_options, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -700,22 +914,61 @@ def update_item_live( collection_id: str, item_id: str, *, - request: CollectionItem, + id: str, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemFieldData] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ Update a selected live Item in a Collection. The updates for this Item will be published to the live site.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + id : str + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published + + last_updated : typing.Optional[str] + The date the item was last updated + + created_on : typing.Optional[str] + The date the item was created + + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived + + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft + + field_data : typing.Optional[CollectionItemFieldData] - - item_id: str. Unique identifier for an Item + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request: CollectionItem. + Returns + ------- + CollectionItem + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import CollectionItem, CollectionItemFieldData + Examples + -------- + from webflow import CollectionItemFieldData from webflow.client import Webflow client = Webflow( @@ -724,61 +977,48 @@ def update_item_live( client.collections.items.update_item_live( collection_id="collection_id", item_id="item_id", - request=CollectionItem( - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", ), ) """ _response = self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + method="PATCH", + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": field_data, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CollectionItem, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + request_options=request_options, + omit=OMIT, + ) try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -790,17 +1030,26 @@ def publish_item( *, item_ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None, - ) -> ItemsPublishItemResponse: + ) -> None: """ Publish an item or multiple items.

Required scope | `cms:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_ids : typing.Sequence[str] - - item_ids: typing.Sequence[str]. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + None + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -812,45 +1061,25 @@ def publish_item( ) """ _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/publish", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder({"itemIds": item_ids}) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder({"itemIds": item_ids}), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ItemsPublishItemResponse, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + f"collections/{jsonable_encoder(collection_id)}/items/publish", + method="POST", + json={"itemIds": item_ids}, + request_options=request_options, + omit=OMIT, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -865,25 +1094,54 @@ async def list_items( self, collection_id: str, *, - cms_locale_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + cms_locale_id: typing.Optional[str] = None, offset: typing.Optional[float] = None, limit: typing.Optional[float] = None, + name: typing.Optional[str] = None, + slug: typing.Optional[str] = None, + sort_by: typing.Optional[ItemsListItemsRequestSortBy] = None, + sort_order: typing.Optional[ItemsListItemsRequestSortOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemList: """ List of all Items within a Collection.

Required scope | `CMS:read` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + name : typing.Optional[str] + The name of the item(s) + + slug : typing.Optional[str] + The slug of the item + + sort_by : typing.Optional[ItemsListItemsRequestSortBy] + Sort results by the provided value - - cms_locale_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]]. Unique identifiers for CMS Locales. These UIDs are different from the Site locale identifier and are listed as `cmsLocaleId` in the Sites response. Applicable when using localization. + sort_order : typing.Optional[ItemsListItemsRequestSortOrder] + Sorts the results by asc or desc - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + Returns + ------- + CollectionItemList + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -894,68 +1152,92 @@ async def list_items( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}/items" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "cmsLocaleIds": cms_locale_ids, - "offset": offset, - "limit": limit, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CollectionItemList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + f"collections/{jsonable_encoder(collection_id)}/items", + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + "offset": offset, + "limit": limit, + "name": name, + "slug": slug, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItemList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) async def create_item( - self, collection_id: str, *, request: CollectionItem, request_options: typing.Optional[RequestOptions] = None + self, + collection_id: str, + *, + id: str, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemFieldData] = OMIT, + request_options: typing.Optional[RequestOptions] = None, ) -> None: """ Create Item in a Collection.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + id : str + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published + + last_updated : typing.Optional[str] + The date the item was last updated - - request: CollectionItem. + created_on : typing.Optional[str] + The date the item was created - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import CollectionItem, CollectionItemFieldData + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived + + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft + + field_data : typing.Optional[CollectionItemFieldData] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from webflow import CollectionItemFieldData from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -963,79 +1245,201 @@ async def create_item( ) await client.collections.items.create_item( collection_id="collection_id", - request=CollectionItem( - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", ), ) """ _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}/items" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"collections/{jsonable_encoder(collection_id)}/items", + method="POST", + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": field_data, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + request_options=request_options, + omit=OMIT, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def list_items_live( + self, + collection_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + name: typing.Optional[str] = None, + slug: typing.Optional[str] = None, + sort_by: typing.Optional[ItemsListItemsLiveRequestSortBy] = None, + sort_order: typing.Optional[ItemsListItemsLiveRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CollectionItemList: + """ + List of all live Items within a Collection.

Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + name : typing.Optional[str] + The name of the item(s) + + slug : typing.Optional[str] + The slug of the item + + sort_by : typing.Optional[ItemsListItemsLiveRequestSortBy] + Sort results by the provided value + + sort_order : typing.Optional[ItemsListItemsLiveRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionItemList + Request was successful + + Examples + -------- + from webflow.client import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + await client.collections.items.list_items_live( + collection_id="collection_id", + ) + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + "offset": offset, + "limit": limit, + "name": name, + "slug": slug, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItemList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) async def create_item_live( - self, collection_id: str, *, request: CollectionItem, request_options: typing.Optional[RequestOptions] = None + self, + collection_id: str, + *, + id: str, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemFieldData] = OMIT, + request_options: typing.Optional[RequestOptions] = None, ) -> None: """ Create live Item in a Collection. This Item will be published to the live site.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + id : str + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published + + last_updated : typing.Optional[str] + The date the item was last updated + + created_on : typing.Optional[str] + The date the item was created + + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived + + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft + + field_data : typing.Optional[CollectionItemFieldData] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request: CollectionItem. + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import CollectionItem, CollectionItemFieldData + Examples + -------- + from webflow import CollectionItemFieldData from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -1043,60 +1447,48 @@ async def create_item_live( ) await client.collections.items.create_item_live( collection_id="collection_id", - request=CollectionItem( - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", ), ) """ _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}/items/live" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"collections/{jsonable_encoder(collection_id)}/items/live", + method="POST", + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": field_data, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + request_options=request_options, + omit=OMIT, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1119,29 +1511,44 @@ async def create_item_for_multiple_locales( """ Create single Item in a Collection with multiple corresponding locales.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + id : str + Unique identifier for the Item + + cms_locale_ids : typing.Optional[typing.Sequence[str]] + Array of identifiers for the locales where the item will be created - - id: str. Unique identifier for the Item + last_published : typing.Optional[str] + The date the item was last published - - cms_locale_ids: typing.Optional[typing.Sequence[str]]. Array of identifiers for the locales where the item will be created + last_updated : typing.Optional[str] + The date the item was last updated - - last_published: typing.Optional[str]. The date the item was last published + created_on : typing.Optional[str] + The date the item was created - - last_updated: typing.Optional[str]. The date the item was last updated + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived - - created_on: typing.Optional[str]. The date the item was created + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft - - is_archived: typing.Optional[bool]. Boolean determining if the Item is set to archived + field_data : typing.Optional[BulkCollectionItemFieldData] - - is_draft: typing.Optional[bool]. Boolean determining if the Item is set to draft + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - field_data: typing.Optional[BulkCollectionItemFieldData]. + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow - from webflow.resources.collections import BulkCollectionItemFieldData client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -1149,69 +1556,37 @@ async def create_item_for_multiple_locales( await client.collections.items.create_item_for_multiple_locales( collection_id="collection_id", id="580e64008c9a982ac9b8b754", - last_published="2023-03-17T18:47:35.560Z", - last_updated="2023-03-17T18:47:35.560Z", - created_on="2023-03-17T18:47:35.560Z", - field_data=BulkCollectionItemFieldData( - name="My new item", - slug="my-new-item", - ), ) """ - _request: typing.Dict[str, typing.Any] = {"id": id} - if cms_locale_ids is not OMIT: - _request["cmsLocaleIds"] = cms_locale_ids - if last_published is not OMIT: - _request["lastPublished"] = last_published - if last_updated is not OMIT: - _request["lastUpdated"] = last_updated - if created_on is not OMIT: - _request["createdOn"] = created_on - if is_archived is not OMIT: - _request["isArchived"] = is_archived - if is_draft is not OMIT: - _request["isDraft"] = is_draft - if field_data is not OMIT: - _request["fieldData"] = field_data _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"collections/{jsonable_encoder(collection_id)}/items/bulk" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"collections/{jsonable_encoder(collection_id)}/items/bulk", + method="POST", + json={ + "id": id, + "cmsLocaleIds": cms_locale_ids, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": field_data, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + request_options=request_options, + omit=OMIT, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1228,15 +1603,27 @@ async def get_item( """ Get details of a selected Collection Item.

Required scope | `CMS:read` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item - - item_id: str. Unique identifier for an Item + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - - cms_locale_id: typing.Optional[str]. Unique identifier for a CMS Locale. These UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. Applicable when using localization. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + CollectionItem + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -1248,48 +1635,24 @@ async def get_item( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "cmsLocaleId": cms_locale_id, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CollectionItem, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + method="GET", + params={"cmsLocaleId": cms_locale_id}, + request_options=request_options, + ) try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1300,21 +1663,32 @@ async def delete_item( collection_id: str, item_id: str, *, - cms_locale_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + cms_locale_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> None: """ Delete an Item from a Collection. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item - - item_id: str. Unique identifier for an Item + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - - cms_locale_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]]. Unique identifiers for CMS Locales. These UIDs are different from the Site locale identifier and are listed as `cmsLocaleId` in the Sites response. Applicable when using localization. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + None + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -1326,48 +1700,24 @@ async def delete_item( ) """ _response = await self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "cmsLocaleIds": cms_locale_ids, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + method="DELETE", + params={"cmsLocaleId": cms_locale_id}, + request_options=request_options, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1378,22 +1728,61 @@ async def update_item( collection_id: str, item_id: str, *, - request: CollectionItem, + id: str, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemFieldData] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ Update a selected Item in a Collection.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + id : str + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published + + last_updated : typing.Optional[str] + The date the item was last updated + + created_on : typing.Optional[str] + The date the item was created + + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived + + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft - - item_id: str. Unique identifier for an Item + field_data : typing.Optional[CollectionItemFieldData] - - request: CollectionItem. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import CollectionItem, CollectionItemFieldData + Returns + ------- + CollectionItem + Request was successful + + Examples + -------- + from webflow import CollectionItemFieldData from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -1402,79 +1791,150 @@ async def update_item( await client.collections.items.update_item( collection_id="collection_id", item_id="item_id", - request=CollectionItem( - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", ), ) """ _response = await self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + method="PATCH", + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": field_data, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CollectionItem, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_item_live( + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CollectionItem: + """ + Get details of a selected Collection live Item.

Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionItem + Request was successful + + Examples + -------- + from webflow.client import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + await client.collections.items.get_item_live( + collection_id="collection_id", + item_id="item_id", + ) + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + method="GET", + params={"cmsLocaleId": cms_locale_id}, + request_options=request_options, + ) try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) async def delete_item_live( - self, collection_id: str, item_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Delete a live Item from a Collection. The Item will be unpublished from the live site. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` + Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - Parameters: - - collection_id: str. Unique identifier for a Collection + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - item_id: str. Unique identifier for an Item + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -1486,39 +1946,24 @@ async def delete_item_live( ) """ _response = await self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + method="DELETE", + params={"cmsLocaleId": cms_locale_id}, + request_options=request_options, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1529,22 +1974,61 @@ async def update_item_live( collection_id: str, item_id: str, *, - request: CollectionItem, + id: str, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemFieldData] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ Update a selected live Item in a Collection. The updates for this Item will be published to the live site.

Required scope | `CMS:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + id : str + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published + + last_updated : typing.Optional[str] + The date the item was last updated + + created_on : typing.Optional[str] + The date the item was created + + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived + + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft + + field_data : typing.Optional[CollectionItemFieldData] - - item_id: str. Unique identifier for an Item + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request: CollectionItem. + Returns + ------- + CollectionItem + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import CollectionItem, CollectionItemFieldData + Examples + -------- + from webflow import CollectionItemFieldData from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -1553,61 +2037,48 @@ async def update_item_live( await client.collections.items.update_item_live( collection_id="collection_id", item_id="item_id", - request=CollectionItem( - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), + id="42b720ef280c7a7a3be8cabe", + cms_locale_id="653ad57de882f528b32e810e", + last_published="2022-11-29T16:22:43.159Z", + last_updated="2022-11-17T17:19:43.282Z", + created_on="2022-11-17T17:11:57.148Z", + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", ), ) """ _response = await self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + method="PATCH", + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": field_data, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CollectionItem, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + request_options=request_options, + omit=OMIT, + ) try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1619,17 +2090,26 @@ async def publish_item( *, item_ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None, - ) -> ItemsPublishItemResponse: + ) -> None: """ Publish an item or multiple items.

Required scope | `cms:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_ids : typing.Sequence[str] - - item_ids: typing.Sequence[str]. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + None + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -1641,45 +2121,25 @@ async def publish_item( ) """ _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/publish", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder({"itemIds": item_ids}) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder({"itemIds": item_ids}), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ItemsPublishItemResponse, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + f"collections/{jsonable_encoder(collection_id)}/items/publish", + method="POST", + json={"itemIds": item_ids}, + request_options=request_options, + omit=OMIT, + ) try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/collections/resources/items/types/__init__.py b/src/webflow/resources/collections/resources/items/types/__init__.py index b313482..fc48f35 100644 --- a/src/webflow/resources/collections/resources/items/types/__init__.py +++ b/src/webflow/resources/collections/resources/items/types/__init__.py @@ -1,6 +1,15 @@ # This file was auto-generated by Fern from our API Definition. from .bulk_collection_item_field_data import BulkCollectionItemFieldData -from .items_publish_item_response import ItemsPublishItemResponse +from .items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy +from .items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder +from .items_list_items_request_sort_by import ItemsListItemsRequestSortBy +from .items_list_items_request_sort_order import ItemsListItemsRequestSortOrder -__all__ = ["BulkCollectionItemFieldData", "ItemsPublishItemResponse"] +__all__ = [ + "BulkCollectionItemFieldData", + "ItemsListItemsLiveRequestSortBy", + "ItemsListItemsLiveRequestSortOrder", + "ItemsListItemsRequestSortBy", + "ItemsListItemsRequestSortOrder", +] diff --git a/src/webflow/resources/collections/resources/items/types/bulk_collection_item_field_data.py b/src/webflow/resources/collections/resources/items/types/bulk_collection_item_field_data.py index 18cb175..dadc943 100644 --- a/src/webflow/resources/collections/resources/items/types/bulk_collection_item_field_data.py +++ b/src/webflow/resources/collections/resources/items/types/bulk_collection_item_field_data.py @@ -4,29 +4,34 @@ import typing from ......core.datetime_utils import serialize_datetime +from ......core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class BulkCollectionItemFieldData(pydantic_v1.BaseModel): + name: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Name of the Item + """ -class BulkCollectionItemFieldData(pydantic.BaseModel): - name: typing.Optional[str] = pydantic.Field(default=None, description="Name of the Item") - slug: typing.Optional[str] = pydantic.Field( - default=None, - description="URL structure of the Item in your site. Note: Updates to an item slug will break all links referencing the old slug.", - ) + slug: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + URL structure of the Item in your site. Note: Updates to an item slug will break all links referencing the old slug. + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_by.py b/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_by.py new file mode 100644 index 0000000..f9f5583 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_by.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class ItemsListItemsLiveRequestSortBy(str, enum.Enum): + LAST_PUBLISHED = "lastPublished" + NAME = "name" + SLUG = "slug" + + def visit( + self, + last_published: typing.Callable[[], T_Result], + name: typing.Callable[[], T_Result], + slug: typing.Callable[[], T_Result], + ) -> T_Result: + if self is ItemsListItemsLiveRequestSortBy.LAST_PUBLISHED: + return last_published() + if self is ItemsListItemsLiveRequestSortBy.NAME: + return name() + if self is ItemsListItemsLiveRequestSortBy.SLUG: + return slug() diff --git a/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_order.py b/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_order.py new file mode 100644 index 0000000..6ce16f4 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_order.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class ItemsListItemsLiveRequestSortOrder(str, enum.Enum): + ASC = "asc" + DESC = "desc" + + def visit(self, asc: typing.Callable[[], T_Result], desc: typing.Callable[[], T_Result]) -> T_Result: + if self is ItemsListItemsLiveRequestSortOrder.ASC: + return asc() + if self is ItemsListItemsLiveRequestSortOrder.DESC: + return desc() diff --git a/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_by.py b/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_by.py new file mode 100644 index 0000000..459f68f --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_by.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class ItemsListItemsRequestSortBy(str, enum.Enum): + LAST_PUBLISHED = "lastPublished" + NAME = "name" + SLUG = "slug" + + def visit( + self, + last_published: typing.Callable[[], T_Result], + name: typing.Callable[[], T_Result], + slug: typing.Callable[[], T_Result], + ) -> T_Result: + if self is ItemsListItemsRequestSortBy.LAST_PUBLISHED: + return last_published() + if self is ItemsListItemsRequestSortBy.NAME: + return name() + if self is ItemsListItemsRequestSortBy.SLUG: + return slug() diff --git a/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_order.py b/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_order.py new file mode 100644 index 0000000..a27080d --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_order.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class ItemsListItemsRequestSortOrder(str, enum.Enum): + ASC = "asc" + DESC = "desc" + + def visit(self, asc: typing.Callable[[], T_Result], desc: typing.Callable[[], T_Result]) -> T_Result: + if self is ItemsListItemsRequestSortOrder.ASC: + return asc() + if self is ItemsListItemsRequestSortOrder.DESC: + return desc() diff --git a/src/webflow/resources/collections/resources/items/types/items_publish_item_response.py b/src/webflow/resources/collections/resources/items/types/items_publish_item_response.py deleted file mode 100644 index 0ecc85f..0000000 --- a/src/webflow/resources/collections/resources/items/types/items_publish_item_response.py +++ /dev/null @@ -1,30 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ......core.datetime_utils import serialize_datetime - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class ItemsPublishItemResponse(pydantic.BaseModel): - published_item_ids: typing.Optional[typing.List[str]] = pydantic.Field(alias="publishedItemIds", default=None) - errors: typing.Optional[typing.List[str]] = None - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/ecommerce/client.py b/src/webflow/resources/ecommerce/client.py index d1d7129..3baa775 100644 --- a/src/webflow/resources/ecommerce/client.py +++ b/src/webflow/resources/ecommerce/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.conflict_error import ConflictError @@ -18,11 +17,6 @@ from ...errors.unauthorized_error import UnauthorizedError from ...types.ecommerce_settings import EcommerceSettings -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - class EcommerceClient: def __init__(self, *, client_wrapper: SyncClientWrapper): @@ -36,11 +30,21 @@ def get_settings( Required scope | `ecommerce:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + EcommerceSettings + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -51,42 +55,25 @@ def get_settings( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/ecommerce/settings" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(EcommerceSettings, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(EcommerceSettings, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -105,11 +92,21 @@ async def get_settings( Required scope | `ecommerce:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + EcommerceSettings + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -120,42 +117,25 @@ async def get_settings( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/ecommerce/settings" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(EcommerceSettings, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(EcommerceSettings, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/forms/client.py b/src/webflow/resources/forms/client.py index e186f96..d5a86a0 100644 --- a/src/webflow/resources/forms/client.py +++ b/src/webflow/resources/forms/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.conflict_error import ConflictError @@ -21,11 +20,6 @@ from ...types.form_submission import FormSubmission from ...types.form_submission_list import FormSubmissionList -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -45,15 +39,27 @@ def list( """ List forms for a given site

Required scope | `forms:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + Returns + ------- + FormList + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -64,50 +70,28 @@ def list( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/forms"), - params=jsonable_encoder( - remove_none_from_dict( - { - "limit": limit, - "offset": offset, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/forms", + method="GET", + params={"limit": limit, "offset": offset}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(FormList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(FormList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -117,11 +101,21 @@ def get(self, form_id: str, *, request_options: typing.Optional[RequestOptions] """ Get information about a given form

Required scope | `forms:read` - Parameters: - - form_id: str. Unique identifier for a Form + Parameters + ---------- + form_id : str + Unique identifier for a Form - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Form + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -132,38 +126,23 @@ def get(self, form_id: str, *, request_options: typing.Optional[RequestOptions] ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"forms/{jsonable_encoder(form_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"forms/{jsonable_encoder(form_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Form, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Form, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -175,11 +154,21 @@ def list_submissions( """ List form submissions for a given form

Required scope | `forms:read` - Parameters: - - form_id: str. Unique identifier for a Form + Parameters + ---------- + form_id : str + Unique identifier for a Form + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + FormSubmissionList + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -190,40 +179,23 @@ def list_submissions( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"forms/{jsonable_encoder(form_id)}/submissions" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"forms/{jsonable_encoder(form_id)}/submissions", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(FormSubmissionList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(FormSubmissionList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -235,11 +207,21 @@ def get_submission( """ Get information about a given form submission

Required scope | `forms:read` - Parameters: - - form_submission_id: str. Unique identifier for a Form Submission + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + FormSubmission + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -250,40 +232,23 @@ def get_submission( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"form_submissions/{jsonable_encoder(form_submission_id)}" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"form_submissions/{jsonable_encoder(form_submission_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(FormSubmission, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(FormSubmission, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -299,13 +264,24 @@ def update_submission( """ Update hidden fields on a form submission

Required scope | `forms:write` - Parameters: - - form_submission_id: str. Unique identifier for a Form Submission + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] + An existing **hidden field** defined on the form schema, and the corresponding value to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - form_submission_data: typing.Optional[typing.Dict[str, typing.Any]]. An existing **hidden field** defined on the form schema, and the corresponding value to set + Returns + ------- + FormSubmission + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -315,52 +291,30 @@ def update_submission( form_submission_id="form_submission_id", ) """ - _request: typing.Dict[str, typing.Any] = {} - if form_submission_data is not OMIT: - _request["formSubmissionData"] = form_submission_data _response = self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"form_submissions/{jsonable_encoder(form_submission_id)}" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"form_submissions/{jsonable_encoder(form_submission_id)}", + method="PATCH", + json={"formSubmissionData": form_submission_data}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(FormSubmission, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(FormSubmission, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -382,15 +336,27 @@ async def list( """ List forms for a given site

Required scope | `forms:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + FormList + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -401,50 +367,28 @@ async def list( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/forms"), - params=jsonable_encoder( - remove_none_from_dict( - { - "limit": limit, - "offset": offset, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/forms", + method="GET", + params={"limit": limit, "offset": offset}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(FormList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(FormList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -454,11 +398,21 @@ async def get(self, form_id: str, *, request_options: typing.Optional[RequestOpt """ Get information about a given form

Required scope | `forms:read` - Parameters: - - form_id: str. Unique identifier for a Form + Parameters + ---------- + form_id : str + Unique identifier for a Form + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Form + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -469,38 +423,23 @@ async def get(self, form_id: str, *, request_options: typing.Optional[RequestOpt ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"forms/{jsonable_encoder(form_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"forms/{jsonable_encoder(form_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Form, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Form, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -512,11 +451,21 @@ async def list_submissions( """ List form submissions for a given form

Required scope | `forms:read` - Parameters: - - form_id: str. Unique identifier for a Form + Parameters + ---------- + form_id : str + Unique identifier for a Form + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + FormSubmissionList + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -527,40 +476,23 @@ async def list_submissions( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"forms/{jsonable_encoder(form_id)}/submissions" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"forms/{jsonable_encoder(form_id)}/submissions", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(FormSubmissionList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(FormSubmissionList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -572,11 +504,21 @@ async def get_submission( """ Get information about a given form submission

Required scope | `forms:read` - Parameters: - - form_submission_id: str. Unique identifier for a Form Submission + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + FormSubmission + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -587,40 +529,23 @@ async def get_submission( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"form_submissions/{jsonable_encoder(form_submission_id)}" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"form_submissions/{jsonable_encoder(form_submission_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(FormSubmission, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(FormSubmission, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -636,13 +561,24 @@ async def update_submission( """ Update hidden fields on a form submission

Required scope | `forms:write` - Parameters: - - form_submission_id: str. Unique identifier for a Form Submission + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] + An existing **hidden field** defined on the form schema, and the corresponding value to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - form_submission_data: typing.Optional[typing.Dict[str, typing.Any]]. An existing **hidden field** defined on the form schema, and the corresponding value to set + Returns + ------- + FormSubmission + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -652,52 +588,30 @@ async def update_submission( form_submission_id="form_submission_id", ) """ - _request: typing.Dict[str, typing.Any] = {} - if form_submission_data is not OMIT: - _request["formSubmissionData"] = form_submission_data _response = await self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"form_submissions/{jsonable_encoder(form_submission_id)}" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"form_submissions/{jsonable_encoder(form_submission_id)}", + method="PATCH", + json={"formSubmissionData": form_submission_data}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(FormSubmission, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(FormSubmission, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/inventory/client.py b/src/webflow/resources/inventory/client.py index 9b9589a..44e16ea 100644 --- a/src/webflow/resources/inventory/client.py +++ b/src/webflow/resources/inventory/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.conflict_error import ConflictError @@ -19,11 +18,6 @@ from ...types.inventory_item import InventoryItem from .types.inventory_update_request_inventory_type import InventoryUpdateRequestInventoryType -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -40,13 +34,24 @@ def list( Required scope | `ecommerce:read` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - item_id: str. Unique identifier for an Item + Returns + ------- + InventoryItem + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -58,43 +63,27 @@ def list( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + method="GET", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(InventoryItem, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(InventoryItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -115,19 +104,33 @@ def update( Required scope | `ecommerce:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + inventory_type : InventoryUpdateRequestInventoryType + infinite or finite - - item_id: str. Unique identifier for an Item + update_quantity : typing.Optional[float] + Adds this quantity to currently store quantity. Can be negative. - - inventory_type: InventoryUpdateRequestInventoryType. infinite or finite + quantity : typing.Optional[float] + Immediately sets quantity to this value. - - update_quantity: typing.Optional[float]. Adds this quantity to currently store quantity. Can be negative. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - quantity: typing.Optional[float]. Immediately sets quantity to this value. + Returns + ------- + InventoryItem + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow import InventoryUpdateRequestInventoryType from webflow.client import Webflow @@ -138,59 +141,32 @@ def update( collection_id="collection_id", item_id="item_id", inventory_type=InventoryUpdateRequestInventoryType.INFINITE, - update_quantity=1.0, - quantity=100.0, ) """ - _request: typing.Dict[str, typing.Any] = {"inventoryType": inventory_type} - if update_quantity is not OMIT: - _request["updateQuantity"] = update_quantity - if quantity is not OMIT: - _request["quantity"] = quantity _response = self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + method="PATCH", + json={"inventoryType": inventory_type, "updateQuantity": update_quantity, "quantity": quantity}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(InventoryItem, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(InventoryItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -209,13 +185,24 @@ async def list( Required scope | `ecommerce:read` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection - - item_id: str. Unique identifier for an Item + item_id : str + Unique identifier for an Item - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + InventoryItem + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -227,43 +214,27 @@ async def list( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + method="GET", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(InventoryItem, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(InventoryItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -284,19 +255,33 @@ async def update( Required scope | `ecommerce:write` - Parameters: - - collection_id: str. Unique identifier for a Collection + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + inventory_type : InventoryUpdateRequestInventoryType + infinite or finite - - item_id: str. Unique identifier for an Item + update_quantity : typing.Optional[float] + Adds this quantity to currently store quantity. Can be negative. - - inventory_type: InventoryUpdateRequestInventoryType. infinite or finite + quantity : typing.Optional[float] + Immediately sets quantity to this value. - - update_quantity: typing.Optional[float]. Adds this quantity to currently store quantity. Can be negative. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - quantity: typing.Optional[float]. Immediately sets quantity to this value. + Returns + ------- + InventoryItem + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow import InventoryUpdateRequestInventoryType from webflow.client import AsyncWebflow @@ -307,59 +292,32 @@ async def update( collection_id="collection_id", item_id="item_id", inventory_type=InventoryUpdateRequestInventoryType.INFINITE, - update_quantity=1.0, - quantity=100.0, ) """ - _request: typing.Dict[str, typing.Any] = {"inventoryType": inventory_type} - if update_quantity is not OMIT: - _request["updateQuantity"] = update_quantity - if quantity is not OMIT: - _request["quantity"] = quantity _response = await self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + method="PATCH", + json={"inventoryType": inventory_type, "updateQuantity": update_quantity, "quantity": quantity}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(InventoryItem, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(InventoryItem, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/orders/__init__.py b/src/webflow/resources/orders/__init__.py index 94cbc01..7076133 100644 --- a/src/webflow/resources/orders/__init__.py +++ b/src/webflow/resources/orders/__init__.py @@ -1,5 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .types import OrdersRefundRequestReason +from .types import OrdersListRequestStatus, OrdersRefundRequestReason -__all__ = ["OrdersRefundRequestReason"] +__all__ = ["OrdersListRequestStatus", "OrdersRefundRequestReason"] diff --git a/src/webflow/resources/orders/client.py b/src/webflow/resources/orders/client.py index 3c079cb..21dc5e8 100644 --- a/src/webflow/resources/orders/client.py +++ b/src/webflow/resources/orders/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.conflict_error import ConflictError @@ -18,13 +17,9 @@ from ...errors.unauthorized_error import UnauthorizedError from ...types.order import Order from ...types.order_list import OrderList +from .types.orders_list_request_status import OrdersListRequestStatus from .types.orders_refund_request_reason import OrdersRefundRequestReason -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -37,7 +32,7 @@ def list( self, site_id: str, *, - status: typing.Optional[str] = None, + status: typing.Optional[OrdersListRequestStatus] = None, offset: typing.Optional[float] = None, limit: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, @@ -47,17 +42,30 @@ def list( Required scope | `ecommerce:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + status : typing.Optional[OrdersListRequestStatus] + Filter the orders by status - - status: typing.Optional[str]. Filter the orders by status + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + OrderList + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -68,53 +76,28 @@ def list( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/orders" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "status": status, - "offset": offset, - "limit": limit, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/orders", + method="GET", + params={"status": status, "offset": offset, "limit": limit}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(OrderList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(OrderList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -126,13 +109,24 @@ def get(self, site_id: str, order_id: str, *, request_options: typing.Optional[R Required scope | `ecommerce:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order - - order_id: str. Unique identifier for an Order + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Order + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -144,43 +138,27 @@ def get(self, site_id: str, order_id: str, *, request_options: typing.Optional[R ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + method="GET", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Order, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -202,21 +180,36 @@ def update( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order - - order_id: str. Unique identifier for an Order + comment : typing.Optional[str] + Arbitrary data for your records - - comment: typing.Optional[str]. Arbitrary data for your records + shipping_provider : typing.Optional[str] + Company or method used to ship order - - shipping_provider: typing.Optional[str]. Company or method used to ship order + shipping_tracking : typing.Optional[str] + Tracking number for order shipment - - shipping_tracking: typing.Optional[str]. Tracking number for order shipment + shipping_tracking_url : typing.Optional[str] + URL to track order shipment - - shipping_tracking_url: typing.Optional[str]. URL to track order shipment + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Order + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -225,65 +218,37 @@ def update( client.orders.update( site_id="site_id", order_id="order_id", - comment="Example comment to myself", - shipping_provider="Shipping Company, Co.", - shipping_tracking="tr00000000001", - shipping_tracking_url="https://www.shippingcompany.com/tracking/tr00000000001", ) """ - _request: typing.Dict[str, typing.Any] = {} - if comment is not OMIT: - _request["comment"] = comment - if shipping_provider is not OMIT: - _request["shippingProvider"] = shipping_provider - if shipping_tracking is not OMIT: - _request["shippingTracking"] = shipping_tracking - if shipping_tracking_url is not OMIT: - _request["shippingTrackingURL"] = shipping_tracking_url _response = self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + method="PATCH", + json={ + "comment": comment, + "shippingProvider": shipping_provider, + "shippingTracking": shipping_tracking, + "shippingTrackingURL": shipping_tracking_url, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Order, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -302,15 +267,27 @@ def update_fulfill( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order - - order_id: str. Unique identifier for an Order + send_order_fulfilled_email : typing.Optional[bool] + Whether or not the Order Fulfilled email should be sent - - send_order_fulfilled_email: typing.Optional[bool]. Whether or not the Order Fulfilled email should be sent + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Order + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -321,53 +298,30 @@ def update_fulfill( order_id="order_id", ) """ - _request: typing.Dict[str, typing.Any] = {} - if send_order_fulfilled_email is not OMIT: - _request["sendOrderFulfilledEmail"] = send_order_fulfilled_email _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", + method="POST", + json={"sendOrderFulfilledEmail": send_order_fulfilled_email}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Order, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -381,13 +335,24 @@ def update_unfulfill( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - order_id: str. Unique identifier for an Order + Returns + ------- + Order + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -399,46 +364,27 @@ def update_unfulfill( ) """ _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {}))) - if request_options is not None - else None, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", + method="POST", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Order, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -458,15 +404,27 @@ def refund( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - order_id: str. Unique identifier for an Order + order_id : str + Unique identifier for an Order - - reason: typing.Optional[OrdersRefundRequestReason]. The reason for the refund + reason : typing.Optional[OrdersRefundRequestReason] + The reason for the refund - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Order + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -477,53 +435,30 @@ def refund( order_id="order_id", ) """ - _request: typing.Dict[str, typing.Any] = {} - if reason is not OMIT: - _request["reason"] = reason.value if reason is not None else None _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", + method="POST", + json={"reason": reason}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Order, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -538,7 +473,7 @@ async def list( self, site_id: str, *, - status: typing.Optional[str] = None, + status: typing.Optional[OrdersListRequestStatus] = None, offset: typing.Optional[float] = None, limit: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, @@ -548,17 +483,30 @@ async def list( Required scope | `ecommerce:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - status: typing.Optional[str]. Filter the orders by status + status : typing.Optional[OrdersListRequestStatus] + Filter the orders by status - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + OrderList + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -569,53 +517,28 @@ async def list( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/orders" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "status": status, - "offset": offset, - "limit": limit, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/orders", + method="GET", + params={"status": status, "offset": offset, "limit": limit}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(OrderList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(OrderList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -629,13 +552,24 @@ async def get( Required scope | `ecommerce:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - order_id: str. Unique identifier for an Order + Returns + ------- + Order + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -647,43 +581,27 @@ async def get( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + method="GET", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Order, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -705,21 +623,36 @@ async def update( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - order_id: str. Unique identifier for an Order + order_id : str + Unique identifier for an Order - - comment: typing.Optional[str]. Arbitrary data for your records + comment : typing.Optional[str] + Arbitrary data for your records - - shipping_provider: typing.Optional[str]. Company or method used to ship order + shipping_provider : typing.Optional[str] + Company or method used to ship order - - shipping_tracking: typing.Optional[str]. Tracking number for order shipment + shipping_tracking : typing.Optional[str] + Tracking number for order shipment - - shipping_tracking_url: typing.Optional[str]. URL to track order shipment + shipping_tracking_url : typing.Optional[str] + URL to track order shipment - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Order + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -728,65 +661,37 @@ async def update( await client.orders.update( site_id="site_id", order_id="order_id", - comment="Example comment to myself", - shipping_provider="Shipping Company, Co.", - shipping_tracking="tr00000000001", - shipping_tracking_url="https://www.shippingcompany.com/tracking/tr00000000001", ) """ - _request: typing.Dict[str, typing.Any] = {} - if comment is not OMIT: - _request["comment"] = comment - if shipping_provider is not OMIT: - _request["shippingProvider"] = shipping_provider - if shipping_tracking is not OMIT: - _request["shippingTracking"] = shipping_tracking - if shipping_tracking_url is not OMIT: - _request["shippingTrackingURL"] = shipping_tracking_url _response = await self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + method="PATCH", + json={ + "comment": comment, + "shippingProvider": shipping_provider, + "shippingTracking": shipping_tracking, + "shippingTrackingURL": shipping_tracking_url, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Order, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -805,15 +710,27 @@ async def update_fulfill( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order - - order_id: str. Unique identifier for an Order + send_order_fulfilled_email : typing.Optional[bool] + Whether or not the Order Fulfilled email should be sent - - send_order_fulfilled_email: typing.Optional[bool]. Whether or not the Order Fulfilled email should be sent + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Order + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -824,53 +741,30 @@ async def update_fulfill( order_id="order_id", ) """ - _request: typing.Dict[str, typing.Any] = {} - if send_order_fulfilled_email is not OMIT: - _request["sendOrderFulfilledEmail"] = send_order_fulfilled_email _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", + method="POST", + json={"sendOrderFulfilledEmail": send_order_fulfilled_email}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Order, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -884,13 +778,24 @@ async def update_unfulfill( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - order_id: str. Unique identifier for an Order + Returns + ------- + Order + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -902,46 +807,27 @@ async def update_unfulfill( ) """ _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {}))) - if request_options is not None - else None, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", + method="POST", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Order, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -961,15 +847,27 @@ async def refund( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - order_id: str. Unique identifier for an Order + order_id : str + Unique identifier for an Order - - reason: typing.Optional[OrdersRefundRequestReason]. The reason for the refund + reason : typing.Optional[OrdersRefundRequestReason] + The reason for the refund - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Order + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -980,53 +878,30 @@ async def refund( order_id="order_id", ) """ - _request: typing.Dict[str, typing.Any] = {} - if reason is not OMIT: - _request["reason"] = reason.value if reason is not None else None _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", + method="POST", + json={"reason": reason}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Order, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/orders/types/__init__.py b/src/webflow/resources/orders/types/__init__.py index a219c24..7df0fa1 100644 --- a/src/webflow/resources/orders/types/__init__.py +++ b/src/webflow/resources/orders/types/__init__.py @@ -1,5 +1,6 @@ # This file was auto-generated by Fern from our API Definition. +from .orders_list_request_status import OrdersListRequestStatus from .orders_refund_request_reason import OrdersRefundRequestReason -__all__ = ["OrdersRefundRequestReason"] +__all__ = ["OrdersListRequestStatus", "OrdersRefundRequestReason"] diff --git a/src/webflow/resources/orders/types/orders_list_request_status.py b/src/webflow/resources/orders/types/orders_list_request_status.py new file mode 100644 index 0000000..ecdfbca --- /dev/null +++ b/src/webflow/resources/orders/types/orders_list_request_status.py @@ -0,0 +1,37 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class OrdersListRequestStatus(str, enum.Enum): + PENDING = "pending" + REFUNDED = "refunded" + DISPUTE_LOST = "dispute-lost" + FULFILLED = "fulfilled" + DISPUTED = "disputed" + UNFULFILLED = "unfulfilled" + + def visit( + self, + pending: typing.Callable[[], T_Result], + refunded: typing.Callable[[], T_Result], + dispute_lost: typing.Callable[[], T_Result], + fulfilled: typing.Callable[[], T_Result], + disputed: typing.Callable[[], T_Result], + unfulfilled: typing.Callable[[], T_Result], + ) -> T_Result: + if self is OrdersListRequestStatus.PENDING: + return pending() + if self is OrdersListRequestStatus.REFUNDED: + return refunded() + if self is OrdersListRequestStatus.DISPUTE_LOST: + return dispute_lost() + if self is OrdersListRequestStatus.FULFILLED: + return fulfilled() + if self is OrdersListRequestStatus.DISPUTED: + return disputed() + if self is OrdersListRequestStatus.UNFULFILLED: + return unfulfilled() diff --git a/src/webflow/resources/pages/__init__.py b/src/webflow/resources/pages/__init__.py index 58f0629..b846071 100644 --- a/src/webflow/resources/pages/__init__.py +++ b/src/webflow/resources/pages/__init__.py @@ -1,6 +1,6 @@ # This file was auto-generated by Fern from our API Definition. -from .types import DomWriteNodesItem +from .types import DomWriteNodesItem, UpdateStaticContentResponse from .resources import scripts -__all__ = ["DomWriteNodesItem", "scripts"] +__all__ = ["DomWriteNodesItem", "UpdateStaticContentResponse", "scripts"] diff --git a/src/webflow/resources/pages/client.py b/src/webflow/resources/pages/client.py index 8b3b1f6..61c1550 100644 --- a/src/webflow/resources/pages/client.py +++ b/src/webflow/resources/pages/client.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. +import datetime as dt import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError @@ -16,15 +16,13 @@ from ...errors.too_many_requests_error import TooManyRequestsError from ...errors.unauthorized_error import UnauthorizedError from ...types.dom import Dom -from ...types.page import Page +from ...types.page_details import PageDetails from ...types.page_list import PageList +from ...types.page_open_graph import PageOpenGraph +from ...types.page_seo import PageSeo from .resources.scripts.client import AsyncScriptsClient, ScriptsClient from .types.dom_write_nodes_item import DomWriteNodesItem - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +from .types.update_static_content_response import UpdateStaticContentResponse # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -47,17 +45,30 @@ def list( """ List of all pages for a site

Required scope | `pages:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + locale : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. - - locale: typing.Optional[str]. Unique identifier for a specific locale. Applicable, when using localization. + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + PageList + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -68,47 +79,24 @@ def list( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/pages"), - params=jsonable_encoder( - remove_none_from_dict( - { - "locale": locale, - "limit": limit, - "offset": offset, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/pages", + method="GET", + params={"locale": locale, "limit": limit, "offset": offset}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(PageList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(PageList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -120,17 +108,28 @@ def get_metadata( *, locale: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> Page: + ) -> PageDetails: """ Get metadata information for a single page

Required scope | `pages:read` - Parameters: - - page_id: str. Unique identifier for a Page + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - locale: typing.Optional[str]. Unique identifier for a specific locale. Applicable, when using localization. + Returns + ------- + PageDetails + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -141,45 +140,24 @@ def get_metadata( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}"), - params=jsonable_encoder( - remove_none_from_dict( - { - "locale": locale, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}", + method="GET", + params={"locale": locale}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Page, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(PageDetails, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -190,24 +168,88 @@ def update_page_settings( page_id: str, *, locale: typing.Optional[str] = None, - request: Page, + id: typing.Optional[str] = OMIT, + site_id: typing.Optional[str] = OMIT, + title: typing.Optional[str] = OMIT, + slug: typing.Optional[str] = OMIT, + parent_id: typing.Optional[str] = OMIT, + collection_id: typing.Optional[str] = OMIT, + created_on: typing.Optional[dt.datetime] = OMIT, + last_updated: typing.Optional[dt.datetime] = OMIT, + archived: typing.Optional[bool] = OMIT, + draft: typing.Optional[bool] = OMIT, + can_branch: typing.Optional[bool] = OMIT, + is_members_only: typing.Optional[bool] = OMIT, + seo: typing.Optional[PageSeo] = OMIT, + open_graph: typing.Optional[PageOpenGraph] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> Page: + ) -> PageDetails: """ Update Page-level metadata, including SEO and Open Graph fields.

Required scope | `pages:write` - Parameters: - - page_id: str. Unique identifier for a Page + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + id : typing.Optional[str] + Unique identifier for the Page + + site_id : typing.Optional[str] + Unique identifier for the Site + + title : typing.Optional[str] + Title of the Page - - locale: typing.Optional[str]. Unique identifier for a specific locale. Applicable, when using localization. + slug : typing.Optional[str] + slug of the Page (derived from title) - - request: Page. + parent_id : typing.Optional[str] + Identifier of the parent folder - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + collection_id : typing.Optional[str] + Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. + + created_on : typing.Optional[dt.datetime] + The date the Page was created + + last_updated : typing.Optional[dt.datetime] + The date the Page was most recently updated + + archived : typing.Optional[bool] + Whether the Page has been archived + + draft : typing.Optional[bool] + Whether the Page is a draft + + can_branch : typing.Optional[bool] + Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) + + is_members_only : typing.Optional[bool] + Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) + + seo : typing.Optional[PageSeo] + SEO-related fields for the Page + + open_graph : typing.Optional[PageOpenGraph] + Open Graph fields for the Page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + PageDetails + Request was successful + + Examples + -------- import datetime - from webflow import Page, PageOpenGraph, PageSeo + from webflow import PageOpenGraph, PageSeo from webflow.client import Webflow client = Webflow( @@ -215,82 +257,69 @@ def update_page_settings( ) client.pages.update_page_settings( page_id="page_id", - request=Page( - id="6390c49774a71f0e3c1a08ee", - site_id="6390c49674a71f84b51a08d8", - title="Blog Categories Template", - slug="detail_blog-category", - parent_id="6419db964a9c435aa3af6251", - collection_id="6390c49774a71f12831a08e3", - created_on=datetime.datetime.fromisoformat( - "2018-10-14 21:55:49+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2022-12-07 16:51:37+00:00", - ), - archived=False, - draft=False, - can_branch=True, - is_members_only=False, - seo=PageSeo( - title="CoffeeStyle eCommerce - Webflow HTML website template", - description="This Webflow template offers a quick start into an e-commerce / memberships site", - ), - open_graph=PageOpenGraph( - title="CoffeeStyle eCommerce - Webflow HTML website template", - title_copied=True, - description="This Webflow template offers a quick start into an e-commerce / memberships site", - description_copied=True, - ), + id="6596da6045e56dee495bcbba", + site_id="6258612d1ee792848f805dcf", + title="Guide to the Galaxy", + slug="guide-to-the-galaxy", + parent_id="6419db964a9c435aa3af6251", + collection_id="6390c49774a71f12831a08e3", + created_on=datetime.datetime.fromisoformat( + "2024-03-11 10:42:00+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2024-03-11 10:42:42+00:00", + ), + archived=False, + draft=False, + can_branch=True, + seo=PageSeo( + title="The Ultimate Hitchhiker's Guide to the Galaxy", + description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", + ), + open_graph=PageOpenGraph( + title="Explore the Cosmos with The Ultimate Guide", + title_copied=False, + description="Dive deep into the mysteries of the universe with your guide to everything galactic.", + description_copied=False, ), ) """ _response = self._client_wrapper.httpx_client.request( - "PUT", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}"), - params=jsonable_encoder( - remove_none_from_dict( - { - "locale": locale, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"pages/{jsonable_encoder(page_id)}", + method="PUT", + params={"locale": locale}, + json={ + "id": id, + "siteId": site_id, + "title": title, + "slug": slug, + "parentId": parent_id, + "collectionId": collection_id, + "createdOn": created_on, + "lastUpdated": last_updated, + "archived": archived, + "draft": draft, + "canBranch": can_branch, + "isMembersOnly": is_members_only, + "seo": seo, + "openGraph": open_graph, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Page, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(PageDetails, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -301,18 +330,37 @@ def get_content( page_id: str, *, locale: typing.Optional[str] = None, + limit: typing.Optional[float] = None, + offset: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, ) -> Dom: """ Get static content from a static page.
If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale

Required scope | `pages:read` - Parameters: - - page_id: str. Unique identifier for a Page + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - locale: typing.Optional[str]. Unique identifier for a specific locale. Applicable, when using localization. + Returns + ------- + Dom + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -323,47 +371,26 @@ def get_content( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}/dom"), - params=jsonable_encoder( - remove_none_from_dict( - { - "locale": locale, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}/dom", + method="GET", + params={"locale": locale, "limit": limit, "offset": offset}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Dom, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Dom, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -376,19 +403,30 @@ def update_static_content( locale: str, nodes: typing.Sequence[DomWriteNodesItem], request_options: typing.Optional[RequestOptions] = None, - ) -> Dom: + ) -> UpdateStaticContentResponse: """ Update static content on a static page. This endpoint supports sending 1000 nodes per request.

Required scope | `pages:write` - Parameters: - - page_id: str. Unique identifier for a Page + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale : str + The locale identifier. - - locale: str. The locale identifier. + nodes : typing.Sequence[DomWriteNodesItem] - - nodes: typing.Sequence[DomWriteNodesItem]. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + UpdateStaticContentResponse + Request was successful + + Examples + -------- from webflow import DomWriteNodesItem from webflow.client import Webflow @@ -400,60 +438,43 @@ def update_static_content( locale="locale", nodes=[ DomWriteNodesItem( - node_id="guide-title-id", - text="

Hello world

", - ) + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", + text="

The Hitchhiker's Guide to the Galaxy

", + ), + DomWriteNodesItem( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + DomWriteNodesItem( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + text="Marvin, the Paranoid Android", + ), ], ) """ _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}/dom"), - params=jsonable_encoder( - remove_none_from_dict( - { - "locale": locale, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - json=jsonable_encoder({"nodes": nodes}) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder({"nodes": nodes}), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}/dom", + method="POST", + params={"locale": locale}, + json={"nodes": nodes}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Dom, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(UpdateStaticContentResponse, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -477,17 +498,30 @@ async def list( """ List of all pages for a site

Required scope | `pages:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - locale: typing.Optional[str]. Unique identifier for a specific locale. Applicable, when using localization. + locale : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + PageList + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -498,47 +532,24 @@ async def list( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/pages"), - params=jsonable_encoder( - remove_none_from_dict( - { - "locale": locale, - "limit": limit, - "offset": offset, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/pages", + method="GET", + params={"locale": locale, "limit": limit, "offset": offset}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(PageList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(PageList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -550,17 +561,28 @@ async def get_metadata( *, locale: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> Page: + ) -> PageDetails: """ Get metadata information for a single page

Required scope | `pages:read` - Parameters: - - page_id: str. Unique identifier for a Page + Parameters + ---------- + page_id : str + Unique identifier for a Page - - locale: typing.Optional[str]. Unique identifier for a specific locale. Applicable, when using localization. + locale : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + PageDetails + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -571,45 +593,24 @@ async def get_metadata( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}"), - params=jsonable_encoder( - remove_none_from_dict( - { - "locale": locale, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}", + method="GET", + params={"locale": locale}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Page, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(PageDetails, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -620,24 +621,88 @@ async def update_page_settings( page_id: str, *, locale: typing.Optional[str] = None, - request: Page, + id: typing.Optional[str] = OMIT, + site_id: typing.Optional[str] = OMIT, + title: typing.Optional[str] = OMIT, + slug: typing.Optional[str] = OMIT, + parent_id: typing.Optional[str] = OMIT, + collection_id: typing.Optional[str] = OMIT, + created_on: typing.Optional[dt.datetime] = OMIT, + last_updated: typing.Optional[dt.datetime] = OMIT, + archived: typing.Optional[bool] = OMIT, + draft: typing.Optional[bool] = OMIT, + can_branch: typing.Optional[bool] = OMIT, + is_members_only: typing.Optional[bool] = OMIT, + seo: typing.Optional[PageSeo] = OMIT, + open_graph: typing.Optional[PageOpenGraph] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> Page: + ) -> PageDetails: """ Update Page-level metadata, including SEO and Open Graph fields.

Required scope | `pages:write` - Parameters: - - page_id: str. Unique identifier for a Page + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + id : typing.Optional[str] + Unique identifier for the Page + + site_id : typing.Optional[str] + Unique identifier for the Site + + title : typing.Optional[str] + Title of the Page + + slug : typing.Optional[str] + slug of the Page (derived from title) - - locale: typing.Optional[str]. Unique identifier for a specific locale. Applicable, when using localization. + parent_id : typing.Optional[str] + Identifier of the parent folder - - request: Page. + collection_id : typing.Optional[str] + Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + created_on : typing.Optional[dt.datetime] + The date the Page was created + + last_updated : typing.Optional[dt.datetime] + The date the Page was most recently updated + + archived : typing.Optional[bool] + Whether the Page has been archived + + draft : typing.Optional[bool] + Whether the Page is a draft + + can_branch : typing.Optional[bool] + Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) + + is_members_only : typing.Optional[bool] + Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) + + seo : typing.Optional[PageSeo] + SEO-related fields for the Page + + open_graph : typing.Optional[PageOpenGraph] + Open Graph fields for the Page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + PageDetails + Request was successful + + Examples + -------- import datetime - from webflow import Page, PageOpenGraph, PageSeo + from webflow import PageOpenGraph, PageSeo from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -645,82 +710,69 @@ async def update_page_settings( ) await client.pages.update_page_settings( page_id="page_id", - request=Page( - id="6390c49774a71f0e3c1a08ee", - site_id="6390c49674a71f84b51a08d8", - title="Blog Categories Template", - slug="detail_blog-category", - parent_id="6419db964a9c435aa3af6251", - collection_id="6390c49774a71f12831a08e3", - created_on=datetime.datetime.fromisoformat( - "2018-10-14 21:55:49+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2022-12-07 16:51:37+00:00", - ), - archived=False, - draft=False, - can_branch=True, - is_members_only=False, - seo=PageSeo( - title="CoffeeStyle eCommerce - Webflow HTML website template", - description="This Webflow template offers a quick start into an e-commerce / memberships site", - ), - open_graph=PageOpenGraph( - title="CoffeeStyle eCommerce - Webflow HTML website template", - title_copied=True, - description="This Webflow template offers a quick start into an e-commerce / memberships site", - description_copied=True, - ), + id="6596da6045e56dee495bcbba", + site_id="6258612d1ee792848f805dcf", + title="Guide to the Galaxy", + slug="guide-to-the-galaxy", + parent_id="6419db964a9c435aa3af6251", + collection_id="6390c49774a71f12831a08e3", + created_on=datetime.datetime.fromisoformat( + "2024-03-11 10:42:00+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2024-03-11 10:42:42+00:00", + ), + archived=False, + draft=False, + can_branch=True, + seo=PageSeo( + title="The Ultimate Hitchhiker's Guide to the Galaxy", + description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", + ), + open_graph=PageOpenGraph( + title="Explore the Cosmos with The Ultimate Guide", + title_copied=False, + description="Dive deep into the mysteries of the universe with your guide to everything galactic.", + description_copied=False, ), ) """ _response = await self._client_wrapper.httpx_client.request( - "PUT", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}"), - params=jsonable_encoder( - remove_none_from_dict( - { - "locale": locale, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"pages/{jsonable_encoder(page_id)}", + method="PUT", + params={"locale": locale}, + json={ + "id": id, + "siteId": site_id, + "title": title, + "slug": slug, + "parentId": parent_id, + "collectionId": collection_id, + "createdOn": created_on, + "lastUpdated": last_updated, + "archived": archived, + "draft": draft, + "canBranch": can_branch, + "isMembersOnly": is_members_only, + "seo": seo, + "openGraph": open_graph, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Page, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(PageDetails, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -731,18 +783,37 @@ async def get_content( page_id: str, *, locale: typing.Optional[str] = None, + limit: typing.Optional[float] = None, + offset: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, ) -> Dom: """ Get static content from a static page.
If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale

Required scope | `pages:read` - Parameters: - - page_id: str. Unique identifier for a Page + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) - - locale: typing.Optional[str]. Unique identifier for a specific locale. Applicable, when using localization. + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Dom + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -753,47 +824,26 @@ async def get_content( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}/dom"), - params=jsonable_encoder( - remove_none_from_dict( - { - "locale": locale, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}/dom", + method="GET", + params={"locale": locale, "limit": limit, "offset": offset}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Dom, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Dom, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -806,19 +856,30 @@ async def update_static_content( locale: str, nodes: typing.Sequence[DomWriteNodesItem], request_options: typing.Optional[RequestOptions] = None, - ) -> Dom: + ) -> UpdateStaticContentResponse: """ Update static content on a static page. This endpoint supports sending 1000 nodes per request.

Required scope | `pages:write` - Parameters: - - page_id: str. Unique identifier for a Page + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale : str + The locale identifier. - - locale: str. The locale identifier. + nodes : typing.Sequence[DomWriteNodesItem] - - nodes: typing.Sequence[DomWriteNodesItem]. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + UpdateStaticContentResponse + Request was successful + + Examples + -------- from webflow import DomWriteNodesItem from webflow.client import AsyncWebflow @@ -830,60 +891,43 @@ async def update_static_content( locale="locale", nodes=[ DomWriteNodesItem( - node_id="guide-title-id", - text="

Hello world

", - ) + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", + text="

The Hitchhiker's Guide to the Galaxy

", + ), + DomWriteNodesItem( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + DomWriteNodesItem( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + text="Marvin, the Paranoid Android", + ), ], ) """ _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}/dom"), - params=jsonable_encoder( - remove_none_from_dict( - { - "locale": locale, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - json=jsonable_encoder({"nodes": nodes}) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder({"nodes": nodes}), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}/dom", + method="POST", + params={"locale": locale}, + json={"nodes": nodes}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Dom, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(UpdateStaticContentResponse, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/pages/resources/scripts/client.py b/src/webflow/resources/pages/resources/scripts/client.py index db07c75..1895650 100644 --- a/src/webflow/resources/pages/resources/scripts/client.py +++ b/src/webflow/resources/pages/resources/scripts/client.py @@ -1,26 +1,21 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from .....core.api_error import ApiError from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.jsonable_encoder import jsonable_encoder -from .....core.remove_none_from_dict import remove_none_from_dict +from .....core.pydantic_utilities import pydantic_v1 from .....core.request_options import RequestOptions from .....errors.bad_request_error import BadRequestError from .....errors.internal_server_error import InternalServerError from .....errors.not_found_error import NotFoundError from .....errors.too_many_requests_error import TooManyRequestsError from .....errors.unauthorized_error import UnauthorizedError +from .....types.script_apply import ScriptApply from .....types.script_apply_list import ScriptApplyList -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -33,13 +28,23 @@ def get_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:read` + Get all registered scripts that have been applied to a specific Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - Parameters: - - page_id: str. Unique identifier for a Page + Returns + ------- + ScriptApplyList + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -50,57 +55,63 @@ def get_custom_code( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}/custom_code", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) def upsert_custom_code( - self, page_id: str, *, request: ScriptApplyList, request_options: typing.Optional[RequestOptions] = None + self, + page_id: str, + *, + scripts: typing.Optional[typing.Sequence[ScriptApply]] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:write` + Add a registered script to a Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + scripts : typing.Optional[typing.Sequence[ScriptApply]] + A list of scripts applied to a Site or a Page - Parameters: - - page_id: str. Unique identifier for a Page + last_updated : typing.Optional[str] + Date when the Site's scripts were last updated - - request: ScriptApplyList. + created_on : typing.Optional[str] + Date when the Site's scripts were created - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import ScriptApply, ScriptApplyList, ScriptApplyLocation + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ScriptApplyList + Request was successful + + Examples + -------- + from webflow import ScriptApply, ScriptApplyLocation from webflow.client import Webflow client = Webflow( @@ -108,67 +119,41 @@ def upsert_custom_code( ) client.pages.scripts.upsert_custom_code( page_id="page_id", - request=ScriptApplyList( - scripts=[ - ScriptApply( - id="cms_slider", - location=ScriptApplyLocation.HEADER, - version="1.0.0", - attributes={"my-attribute": "some-value"}, - ), - ScriptApply( - id="alert", - location=ScriptApplyLocation.HEADER, - version="0.0.1", - ), - ScriptApply( - id="id", - location=ScriptApplyLocation.HEADER, - version="version", - ), - ], - ), + scripts=[ + ScriptApply( + id="cms_slider", + location=ScriptApplyLocation.HEADER, + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location=ScriptApplyLocation.HEADER, + version="0.0.1", + ), + ], ) """ _response = self._client_wrapper.httpx_client.request( - "PUT", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}/custom_code", + method="PUT", + json={"scripts": scripts, "lastUpdated": last_updated, "createdOn": created_on}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -176,13 +161,22 @@ def upsert_custom_code( def delete_custom_code(self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete the custom code block that an app has created for a page

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:write` + Delete the custom code block that an app has created for a page

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - Parameters: - - page_id: str. Unique identifier for a Page + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -193,38 +187,21 @@ def delete_custom_code(self, page_id: str, *, request_options: typing.Optional[R ) """ _response = self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}/custom_code", method="DELETE", request_options=request_options ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -239,13 +216,23 @@ async def get_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:read` + Get all registered scripts that have been applied to a specific Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` - Parameters: - - page_id: str. Unique identifier for a Page + Parameters + ---------- + page_id : str + Unique identifier for a Page - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ScriptApplyList + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -256,57 +243,63 @@ async def get_custom_code( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}/custom_code", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) async def upsert_custom_code( - self, page_id: str, *, request: ScriptApplyList, request_options: typing.Optional[RequestOptions] = None + self, + page_id: str, + *, + scripts: typing.Optional[typing.Sequence[ScriptApply]] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:write` + Add a registered script to a Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + scripts : typing.Optional[typing.Sequence[ScriptApply]] + A list of scripts applied to a Site or a Page - Parameters: - - page_id: str. Unique identifier for a Page + last_updated : typing.Optional[str] + Date when the Site's scripts were last updated - - request: ScriptApplyList. + created_on : typing.Optional[str] + Date when the Site's scripts were created - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import ScriptApply, ScriptApplyList, ScriptApplyLocation + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ScriptApplyList + Request was successful + + Examples + -------- + from webflow import ScriptApply, ScriptApplyLocation from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -314,67 +307,41 @@ async def upsert_custom_code( ) await client.pages.scripts.upsert_custom_code( page_id="page_id", - request=ScriptApplyList( - scripts=[ - ScriptApply( - id="cms_slider", - location=ScriptApplyLocation.HEADER, - version="1.0.0", - attributes={"my-attribute": "some-value"}, - ), - ScriptApply( - id="alert", - location=ScriptApplyLocation.HEADER, - version="0.0.1", - ), - ScriptApply( - id="id", - location=ScriptApplyLocation.HEADER, - version="version", - ), - ], - ), + scripts=[ + ScriptApply( + id="cms_slider", + location=ScriptApplyLocation.HEADER, + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location=ScriptApplyLocation.HEADER, + version="0.0.1", + ), + ], ) """ _response = await self._client_wrapper.httpx_client.request( - "PUT", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}/custom_code", + method="PUT", + json={"scripts": scripts, "lastUpdated": last_updated, "createdOn": created_on}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -384,13 +351,22 @@ async def delete_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> None: """ - Delete the custom code block that an app has created for a page

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:write` + Delete the custom code block that an app has created for a page

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - Parameters: - - page_id: str. Unique identifier for a Page + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -401,38 +377,21 @@ async def delete_custom_code( ) """ _response = await self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"pages/{jsonable_encoder(page_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"pages/{jsonable_encoder(page_id)}/custom_code", method="DELETE", request_options=request_options ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/pages/types/__init__.py b/src/webflow/resources/pages/types/__init__.py index fdefa12..0903928 100644 --- a/src/webflow/resources/pages/types/__init__.py +++ b/src/webflow/resources/pages/types/__init__.py @@ -1,5 +1,6 @@ # This file was auto-generated by Fern from our API Definition. from .dom_write_nodes_item import DomWriteNodesItem +from .update_static_content_response import UpdateStaticContentResponse -__all__ = ["DomWriteNodesItem"] +__all__ = ["DomWriteNodesItem", "UpdateStaticContentResponse"] diff --git a/src/webflow/resources/pages/types/dom_write_nodes_item.py b/src/webflow/resources/pages/types/dom_write_nodes_item.py index 36f7d9b..b37b43b 100644 --- a/src/webflow/resources/pages/types/dom_write_nodes_item.py +++ b/src/webflow/resources/pages/types/dom_write_nodes_item.py @@ -4,27 +4,36 @@ import typing from ....core.datetime_utils import serialize_datetime +from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class DomWriteNodesItem(pydantic_v1.BaseModel): + node_id: str = pydantic_v1.Field(alias="nodeId") + """ + Node UUID + """ -class DomWriteNodesItem(pydantic.BaseModel): - node_id: str = pydantic.Field(alias="nodeId", description="Node UUID") - text: str = pydantic.Field(description="HTML content of the node") + text: str = pydantic_v1.Field() + """ + HTML content of the node, including the HTML tag. The HTML tags must be the same as what's returned from the Get Content endpoint. + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/pages/types/update_static_content_response.py b/src/webflow/resources/pages/types/update_static_content_response.py new file mode 100644 index 0000000..f960341 --- /dev/null +++ b/src/webflow/resources/pages/types/update_static_content_response.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ....core.datetime_utils import serialize_datetime +from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 + + +class UpdateStaticContentResponse(pydantic_v1.BaseModel): + errors: typing.List[str] = pydantic_v1.Field() + """ + A list of error messages, if any. + """ + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) + + class Config: + frozen = True + smart_union = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/products/__init__.py b/src/webflow/resources/products/__init__.py index d1569c5..9fced2c 100644 --- a/src/webflow/resources/products/__init__.py +++ b/src/webflow/resources/products/__init__.py @@ -1,31 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .types import ( - ProductSkuCreateProduct, - ProductSkuCreateProductFieldData, - ProductSkuCreateProductFieldDataEcProductType, - ProductSkuCreateProductFieldDataTaxCategory, - ProductSkuCreateSku, - ProductSkuCreateSkuFieldData, - ProductSkuCreateSkuFieldDataCompareAtPrice, - ProductSkuCreateSkuFieldDataEcSkuBillingMethod, - ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlan, - ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval, - ProductSkuCreateSkuFieldDataPrice, - ProductsCreateSkuResponse, -) +from .types import ProductsCreateSkuResponse -__all__ = [ - "ProductSkuCreateProduct", - "ProductSkuCreateProductFieldData", - "ProductSkuCreateProductFieldDataEcProductType", - "ProductSkuCreateProductFieldDataTaxCategory", - "ProductSkuCreateSku", - "ProductSkuCreateSkuFieldData", - "ProductSkuCreateSkuFieldDataCompareAtPrice", - "ProductSkuCreateSkuFieldDataEcSkuBillingMethod", - "ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlan", - "ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval", - "ProductSkuCreateSkuFieldDataPrice", - "ProductsCreateSkuResponse", -] +__all__ = ["ProductsCreateSkuResponse"] diff --git a/src/webflow/resources/products/client.py b/src/webflow/resources/products/client.py index 4d7180a..fb1896e 100644 --- a/src/webflow/resources/products/client.py +++ b/src/webflow/resources/products/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.conflict_error import ConflictError @@ -21,15 +20,8 @@ from ...types.product_and_sk_us_list import ProductAndSkUsList from ...types.publish_status import PublishStatus from ...types.sku import Sku -from .types.product_sku_create_product import ProductSkuCreateProduct -from .types.product_sku_create_sku import ProductSkuCreateSku from .types.products_create_sku_response import ProductsCreateSkuResponse -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -51,15 +43,27 @@ def list( Required scope | `ecommerce:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + ProductAndSkUsList + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -70,52 +74,28 @@ def list( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/products" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "offset": offset, - "limit": limit, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products", + method="GET", + params={"offset": offset, "limit": limit}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ProductAndSkUsList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ProductAndSkUsList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -126,8 +106,8 @@ def create( site_id: str, *, publish_status: typing.Optional[PublishStatus] = OMIT, - product: typing.Optional[ProductSkuCreateProduct] = OMIT, - sku: typing.Optional[ProductSkuCreateSku] = OMIT, + product: typing.Optional[Product] = OMIT, + sku: typing.Optional[Sku] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUs: """ @@ -141,17 +121,27 @@ def create( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + publish_status : typing.Optional[PublishStatus] - - publish_status: typing.Optional[PublishStatus]. + product : typing.Optional[Product] - - product: typing.Optional[ProductSkuCreateProduct]. The Product Object + sku : typing.Optional[Sku] - - sku: typing.Optional[ProductSkuCreateSku]. The SKU object + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + ProductAndSkUs + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -161,56 +151,30 @@ def create( site_id="site_id", ) """ - _request: typing.Dict[str, typing.Any] = {} - if publish_status is not OMIT: - _request["publishStatus"] = publish_status.value if publish_status is not None else None - if product is not OMIT: - _request["product"] = product - if sku is not OMIT: - _request["sku"] = sku _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/products" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products", + method="POST", + json={"publishStatus": publish_status, "product": product, "sku": sku}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -224,13 +188,24 @@ def get( Required scope | `ecommerce:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product - - product_id: str. Unique identifier for a Product + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + ProductAndSkUs + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -242,43 +217,27 @@ def get( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + method="GET", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -290,7 +249,8 @@ def update( product_id: str, *, publish_status: typing.Optional[PublishStatus] = OMIT, - product: Product, + product: typing.Optional[Product] = OMIT, + sku: typing.Optional[Sku] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Product: """ @@ -298,25 +258,30 @@ def update( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - product_id: str. Unique identifier for a Product + product_id : str + Unique identifier for a Product - - publish_status: typing.Optional[PublishStatus]. + publish_status : typing.Optional[PublishStatus] - - product: Product. + product : typing.Optional[Product] - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - import datetime + sku : typing.Optional[Sku] - from webflow import ( - Product, - ProductFieldData, - SkuPropertyList, - SkuPropertyListEnumItem, - ) + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Product + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -325,114 +290,32 @@ def update( client.products.update( site_id="site_id", product_id="product_id", - product=Product( - id="580e63fc8c9a982ac9b8b745", - last_published=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - created_on=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - is_archived=False, - is_draft=False, - field_data=ProductFieldData( - name="T-Shirt", - slug="t-shirt", - description="A plain cotton t-shirt.", - shippable=True, - sku_properties=[ - SkuPropertyList( - id="color", - name="Color", - enum=[ - SkuPropertyListEnumItem( - id="royal-blue", - name="Royal Blue", - slug="royal-blue", - ), - SkuPropertyListEnumItem( - id="crimson-red", - name="Crimson Red", - slug="crimson-red", - ), - SkuPropertyListEnumItem( - id="forrest-green", - name="name", - slug="slug", - ), - SkuPropertyListEnumItem( - id="id", - name="name", - slug="slug", - ), - ], - ), - SkuPropertyList( - id="Color", - name="Color", - enum=[ - SkuPropertyListEnumItem( - id="id", - name="name", - slug="slug", - ) - ], - ), - ], - ), - ), ) """ - _request: typing.Dict[str, typing.Any] = {"product": product} - if publish_status is not OMIT: - _request["publishStatus"] = publish_status.value if publish_status is not None else None _response = self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + method="PATCH", + json={"publishStatus": publish_status, "product": product, "sku": sku}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Product, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Product, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -443,8 +326,8 @@ def create_sku( site_id: str, product_id: str, *, - publish_status: typing.Optional[PublishStatus] = OMIT, skus: typing.Sequence[Sku], + publish_status: typing.Optional[PublishStatus] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> ProductsCreateSkuResponse: """ @@ -454,20 +337,30 @@ def create_sku( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - product_id: str. Unique identifier for a Product + product_id : str + Unique identifier for a Product - - publish_status: typing.Optional[PublishStatus]. + skus : typing.Sequence[Sku] + An array of the SKU data your are adding - - skus: typing.Sequence[Sku]. An array of the SKU data your are adding + publish_status : typing.Optional[PublishStatus] - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - import datetime + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - from webflow import Sku, SkuFieldData, SkuFieldDataPrice + Returns + ------- + ProductsCreateSkuResponse + Request was successful + + Examples + -------- + from webflow import Sku from webflow.client import Webflow client = Webflow( @@ -476,78 +369,33 @@ def create_sku( client.products.create_sku( site_id="site_id", product_id="product_id", - skus=[ - Sku( - id="580e63fc8c9a982ac9b8b745", - last_published=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - created_on=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - field_data=SkuFieldData( - name="Blue T-shirt", - slug="t-shirt-blue", - price=SkuFieldDataPrice( - value=100.0, - unit="USD", - ), - quantity=10.0, - ), - ) - ], + skus=[Sku()], ) """ - _request: typing.Dict[str, typing.Any] = {"skus": skus} - if publish_status is not OMIT: - _request["publishStatus"] = publish_status.value if publish_status is not None else None _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", + method="POST", + json={"publishStatus": publish_status, "skus": skus}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ProductsCreateSkuResponse, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ProductsCreateSkuResponse, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -559,8 +407,8 @@ def update_sku( product_id: str, sku_id: str, *, - publish_status: typing.Optional[PublishStatus] = OMIT, sku: Sku, + publish_status: typing.Optional[PublishStatus] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Sku: """ @@ -568,22 +416,32 @@ def update_sku( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product - - product_id: str. Unique identifier for a Product + sku_id : str + Unique identifier for a SKU - - sku_id: str. Unique identifier for a SKU + sku : Sku - - publish_status: typing.Optional[PublishStatus]. + publish_status : typing.Optional[PublishStatus] - - sku: Sku. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - import datetime + Returns + ------- + Sku + Request was successful - from webflow import Sku, SkuFieldData, SkuFieldDataPrice + Examples + -------- + from webflow import Sku from webflow.client import Webflow client = Webflow( @@ -593,76 +451,33 @@ def update_sku( site_id="site_id", product_id="product_id", sku_id="sku_id", - sku=Sku( - id="580e63fc8c9a982ac9b8b745", - last_published=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - created_on=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - field_data=SkuFieldData( - name="Blue T-shirt", - slug="t-shirt-blue", - price=SkuFieldDataPrice( - value=100.0, - unit="USD", - ), - quantity=10.0, - ), - ), + sku=Sku(), ) """ - _request: typing.Dict[str, typing.Any] = {"sku": sku} - if publish_status is not OMIT: - _request["publishStatus"] = publish_status.value if publish_status is not None else None _response = self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", + method="PATCH", + json={"publishStatus": publish_status, "sku": sku}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Sku, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Sku, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -686,15 +501,27 @@ async def list( Required scope | `ecommerce:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ProductAndSkUsList + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -705,52 +532,28 @@ async def list( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/products" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "offset": offset, - "limit": limit, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products", + method="GET", + params={"offset": offset, "limit": limit}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ProductAndSkUsList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ProductAndSkUsList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -761,8 +564,8 @@ async def create( site_id: str, *, publish_status: typing.Optional[PublishStatus] = OMIT, - product: typing.Optional[ProductSkuCreateProduct] = OMIT, - sku: typing.Optional[ProductSkuCreateSku] = OMIT, + product: typing.Optional[Product] = OMIT, + sku: typing.Optional[Sku] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUs: """ @@ -776,17 +579,27 @@ async def create( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + publish_status : typing.Optional[PublishStatus] + + product : typing.Optional[Product] - - publish_status: typing.Optional[PublishStatus]. + sku : typing.Optional[Sku] - - product: typing.Optional[ProductSkuCreateProduct]. The Product Object + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - sku: typing.Optional[ProductSkuCreateSku]. The SKU object + Returns + ------- + ProductAndSkUs + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -796,56 +609,30 @@ async def create( site_id="site_id", ) """ - _request: typing.Dict[str, typing.Any] = {} - if publish_status is not OMIT: - _request["publishStatus"] = publish_status.value if publish_status is not None else None - if product is not OMIT: - _request["product"] = product - if sku is not OMIT: - _request["sku"] = sku _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/products" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products", + method="POST", + json={"publishStatus": publish_status, "product": product, "sku": sku}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -859,13 +646,24 @@ async def get( Required scope | `ecommerce:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - product_id: str. Unique identifier for a Product + product_id : str + Unique identifier for a Product - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ProductAndSkUs + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -877,43 +675,27 @@ async def get( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + method="GET", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -925,7 +707,8 @@ async def update( product_id: str, *, publish_status: typing.Optional[PublishStatus] = OMIT, - product: Product, + product: typing.Optional[Product] = OMIT, + sku: typing.Optional[Sku] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Product: """ @@ -933,25 +716,30 @@ async def update( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - product_id: str. Unique identifier for a Product + product_id : str + Unique identifier for a Product - - publish_status: typing.Optional[PublishStatus]. + publish_status : typing.Optional[PublishStatus] - - product: Product. + product : typing.Optional[Product] - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - import datetime + sku : typing.Optional[Sku] - from webflow import ( - Product, - ProductFieldData, - SkuPropertyList, - SkuPropertyListEnumItem, - ) + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Product + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -960,114 +748,32 @@ async def update( await client.products.update( site_id="site_id", product_id="product_id", - product=Product( - id="580e63fc8c9a982ac9b8b745", - last_published=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - created_on=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - is_archived=False, - is_draft=False, - field_data=ProductFieldData( - name="T-Shirt", - slug="t-shirt", - description="A plain cotton t-shirt.", - shippable=True, - sku_properties=[ - SkuPropertyList( - id="color", - name="Color", - enum=[ - SkuPropertyListEnumItem( - id="royal-blue", - name="Royal Blue", - slug="royal-blue", - ), - SkuPropertyListEnumItem( - id="crimson-red", - name="Crimson Red", - slug="crimson-red", - ), - SkuPropertyListEnumItem( - id="forrest-green", - name="name", - slug="slug", - ), - SkuPropertyListEnumItem( - id="id", - name="name", - slug="slug", - ), - ], - ), - SkuPropertyList( - id="Color", - name="Color", - enum=[ - SkuPropertyListEnumItem( - id="id", - name="name", - slug="slug", - ) - ], - ), - ], - ), - ), ) """ - _request: typing.Dict[str, typing.Any] = {"product": product} - if publish_status is not OMIT: - _request["publishStatus"] = publish_status.value if publish_status is not None else None _response = await self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + method="PATCH", + json={"publishStatus": publish_status, "product": product, "sku": sku}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Product, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Product, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1078,8 +784,8 @@ async def create_sku( site_id: str, product_id: str, *, - publish_status: typing.Optional[PublishStatus] = OMIT, skus: typing.Sequence[Sku], + publish_status: typing.Optional[PublishStatus] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> ProductsCreateSkuResponse: """ @@ -1089,20 +795,30 @@ async def create_sku( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product - - product_id: str. Unique identifier for a Product + skus : typing.Sequence[Sku] + An array of the SKU data your are adding - - publish_status: typing.Optional[PublishStatus]. + publish_status : typing.Optional[PublishStatus] - - skus: typing.Sequence[Sku]. An array of the SKU data your are adding + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - import datetime + Returns + ------- + ProductsCreateSkuResponse + Request was successful - from webflow import Sku, SkuFieldData, SkuFieldDataPrice + Examples + -------- + from webflow import Sku from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -1111,78 +827,33 @@ async def create_sku( await client.products.create_sku( site_id="site_id", product_id="product_id", - skus=[ - Sku( - id="580e63fc8c9a982ac9b8b745", - last_published=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - created_on=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - field_data=SkuFieldData( - name="Blue T-shirt", - slug="t-shirt-blue", - price=SkuFieldDataPrice( - value=100.0, - unit="USD", - ), - quantity=10.0, - ), - ) - ], + skus=[Sku()], ) """ - _request: typing.Dict[str, typing.Any] = {"skus": skus} - if publish_status is not OMIT: - _request["publishStatus"] = publish_status.value if publish_status is not None else None _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", + method="POST", + json={"publishStatus": publish_status, "skus": skus}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ProductsCreateSkuResponse, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ProductsCreateSkuResponse, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1194,8 +865,8 @@ async def update_sku( product_id: str, sku_id: str, *, - publish_status: typing.Optional[PublishStatus] = OMIT, sku: Sku, + publish_status: typing.Optional[PublishStatus] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Sku: """ @@ -1203,22 +874,32 @@ async def update_sku( Required scope | `ecommerce:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product - - product_id: str. Unique identifier for a Product + sku_id : str + Unique identifier for a SKU - - sku_id: str. Unique identifier for a SKU + sku : Sku - - publish_status: typing.Optional[PublishStatus]. + publish_status : typing.Optional[PublishStatus] - - sku: Sku. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - import datetime + Returns + ------- + Sku + Request was successful - from webflow import Sku, SkuFieldData, SkuFieldDataPrice + Examples + -------- + from webflow import Sku from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -1228,76 +909,33 @@ async def update_sku( site_id="site_id", product_id="product_id", sku_id="sku_id", - sku=Sku( - id="580e63fc8c9a982ac9b8b745", - last_published=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - created_on=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - field_data=SkuFieldData( - name="Blue T-shirt", - slug="t-shirt-blue", - price=SkuFieldDataPrice( - value=100.0, - unit="USD", - ), - quantity=10.0, - ), - ), + sku=Sku(), ) """ - _request: typing.Dict[str, typing.Any] = {"sku": sku} - if publish_status is not OMIT: - _request["publishStatus"] = publish_status.value if publish_status is not None else None _response = await self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", + method="PATCH", + json={"publishStatus": publish_status, "sku": sku}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Sku, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Sku, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/products/types/__init__.py b/src/webflow/resources/products/types/__init__.py index 55ac9d6..b078afe 100644 --- a/src/webflow/resources/products/types/__init__.py +++ b/src/webflow/resources/products/types/__init__.py @@ -1,33 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .product_sku_create_product import ProductSkuCreateProduct -from .product_sku_create_product_field_data import ProductSkuCreateProductFieldData -from .product_sku_create_product_field_data_ec_product_type import ProductSkuCreateProductFieldDataEcProductType -from .product_sku_create_product_field_data_tax_category import ProductSkuCreateProductFieldDataTaxCategory -from .product_sku_create_sku import ProductSkuCreateSku -from .product_sku_create_sku_field_data import ProductSkuCreateSkuFieldData -from .product_sku_create_sku_field_data_compare_at_price import ProductSkuCreateSkuFieldDataCompareAtPrice -from .product_sku_create_sku_field_data_ec_sku_billing_method import ProductSkuCreateSkuFieldDataEcSkuBillingMethod -from .product_sku_create_sku_field_data_ec_sku_subscription_plan import ( - ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlan, -) -from .product_sku_create_sku_field_data_ec_sku_subscription_plan_interval import ( - ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval, -) -from .product_sku_create_sku_field_data_price import ProductSkuCreateSkuFieldDataPrice from .products_create_sku_response import ProductsCreateSkuResponse -__all__ = [ - "ProductSkuCreateProduct", - "ProductSkuCreateProductFieldData", - "ProductSkuCreateProductFieldDataEcProductType", - "ProductSkuCreateProductFieldDataTaxCategory", - "ProductSkuCreateSku", - "ProductSkuCreateSkuFieldData", - "ProductSkuCreateSkuFieldDataCompareAtPrice", - "ProductSkuCreateSkuFieldDataEcSkuBillingMethod", - "ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlan", - "ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval", - "ProductSkuCreateSkuFieldDataPrice", - "ProductsCreateSkuResponse", -] +__all__ = ["ProductsCreateSkuResponse"] diff --git a/src/webflow/resources/products/types/product_sku_create_product.py b/src/webflow/resources/products/types/product_sku_create_product.py deleted file mode 100644 index 6e410b8..0000000 --- a/src/webflow/resources/products/types/product_sku_create_product.py +++ /dev/null @@ -1,50 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ....core.datetime_utils import serialize_datetime -from .product_sku_create_product_field_data import ProductSkuCreateProductFieldData - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class ProductSkuCreateProduct(pydantic.BaseModel): - """ - The Product Object - """ - - id: typing.Optional[str] = pydantic.Field(default=None, description="Unique identifier for the Product") - last_published: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastPublished", default=None, description="The date the Product was last published" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="The date the Product was last updated" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The date the Product was created" - ) - is_archived: typing.Optional[bool] = pydantic.Field( - alias="isArchived", default=None, description="Boolean determining if the Product is set to archived" - ) - is_draft: typing.Optional[bool] = pydantic.Field( - alias="isDraft", default=None, description="Boolean determining if the Product is set to draft" - ) - field_data: typing.Optional[ProductSkuCreateProductFieldData] = pydantic.Field(alias="fieldData", default=None) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/products/types/product_sku_create_product_field_data.py b/src/webflow/resources/products/types/product_sku_create_product_field_data.py deleted file mode 100644 index 2748896..0000000 --- a/src/webflow/resources/products/types/product_sku_create_product_field_data.py +++ /dev/null @@ -1,52 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ....core.datetime_utils import serialize_datetime -from ....types.sku_property_list import SkuPropertyList -from .product_sku_create_product_field_data_ec_product_type import ProductSkuCreateProductFieldDataEcProductType -from .product_sku_create_product_field_data_tax_category import ProductSkuCreateProductFieldDataTaxCategory - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class ProductSkuCreateProductFieldData(pydantic.BaseModel): - name: str = pydantic.Field(description="Name of the Product") - slug: str = pydantic.Field(description="URL structure of the Product in your site.") - description: typing.Optional[str] = pydantic.Field(default=None, description="A description of your product") - shippable: typing.Optional[bool] = pydantic.Field( - default=None, description="Boolean determining if the Product is shippable" - ) - sku_properties: typing.Optional[typing.List[SkuPropertyList]] = pydantic.Field( - alias="sku-properties", default=None, description="Variant types to include in SKUs" - ) - categories: typing.Optional[typing.List[typing.Any]] = pydantic.Field( - default=None, description="The categories your product belongs to." - ) - tax_category: typing.Optional[ProductSkuCreateProductFieldDataTaxCategory] = pydantic.Field( - alias="tax-category", default=None, description="Product tax class" - ) - ec_product_type: typing.Optional[ProductSkuCreateProductFieldDataEcProductType] = pydantic.Field( - alias="ec-product-type", - default=None, - description='Product types. Enums reflect the following values in order: Physical, Digital, Service, Advanced"', - ) - additional_properties: typing.Optional[typing.Any] = pydantic.Field(alias="additionalProperties", default=None) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/products/types/product_sku_create_product_field_data_ec_product_type.py b/src/webflow/resources/products/types/product_sku_create_product_field_data_ec_product_type.py deleted file mode 100644 index 05f521c..0000000 --- a/src/webflow/resources/products/types/product_sku_create_product_field_data_ec_product_type.py +++ /dev/null @@ -1,33 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import enum -import typing - -T_Result = typing.TypeVar("T_Result") - - -class ProductSkuCreateProductFieldDataEcProductType(str, enum.Enum): - """ - Product types. Enums reflect the following values in order: Physical, Digital, Service, Advanced" - """ - - FF_42_FEE_0113744_F_693_A_764_E_3431_A_9_CC_2 = "ff42fee0113744f693a764e3431a9cc2" - F_22027_DB_68002190_AEF_89_A_4_A_2_B_7_AC_8_A_1 = "f22027db68002190aef89a4a2b7ac8a1" - C_599_E_43_B_1_A_1_C_34_D_5_A_323_AEDF_75_D_3_ADF_6 = "c599e43b1a1c34d5a323aedf75d3adf6" - B_6_CCC_1830_DB_4_B_1_BABEB_06_A_9_AC_5_F_6_DD_76 = "b6ccc1830db4b1babeb06a9ac5f6dd76" - - def visit( - self, - ff_42_fee_0113744_f_693_a_764_e_3431_a_9_cc_2: typing.Callable[[], T_Result], - f_22027_db_68002190_aef_89_a_4_a_2_b_7_ac_8_a_1: typing.Callable[[], T_Result], - c_599_e_43_b_1_a_1_c_34_d_5_a_323_aedf_75_d_3_adf_6: typing.Callable[[], T_Result], - b_6_ccc_1830_db_4_b_1_babeb_06_a_9_ac_5_f_6_dd_76: typing.Callable[[], T_Result], - ) -> T_Result: - if self is ProductSkuCreateProductFieldDataEcProductType.FF_42_FEE_0113744_F_693_A_764_E_3431_A_9_CC_2: - return ff_42_fee_0113744_f_693_a_764_e_3431_a_9_cc_2() - if self is ProductSkuCreateProductFieldDataEcProductType.F_22027_DB_68002190_AEF_89_A_4_A_2_B_7_AC_8_A_1: - return f_22027_db_68002190_aef_89_a_4_a_2_b_7_ac_8_a_1() - if self is ProductSkuCreateProductFieldDataEcProductType.C_599_E_43_B_1_A_1_C_34_D_5_A_323_AEDF_75_D_3_ADF_6: - return c_599_e_43_b_1_a_1_c_34_d_5_a_323_aedf_75_d_3_adf_6() - if self is ProductSkuCreateProductFieldDataEcProductType.B_6_CCC_1830_DB_4_B_1_BABEB_06_A_9_AC_5_F_6_DD_76: - return b_6_ccc_1830_db_4_b_1_babeb_06_a_9_ac_5_f_6_dd_76() diff --git a/src/webflow/resources/products/types/product_sku_create_product_field_data_tax_category.py b/src/webflow/resources/products/types/product_sku_create_product_field_data_tax_category.py deleted file mode 100644 index a2eb210..0000000 --- a/src/webflow/resources/products/types/product_sku_create_product_field_data_tax_category.py +++ /dev/null @@ -1,133 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import enum -import typing - -T_Result = typing.TypeVar("T_Result") - - -class ProductSkuCreateProductFieldDataTaxCategory(str, enum.Enum): - """ - Product tax class - """ - - STANDARD_TAXABLE = "standard-taxable" - STANDARD_EXEMPT = "standard-exempt" - BOOKS_RELIGIOUS = "books-religious" - BOOKS_TEXTBOOK = "books-textbook" - CLOTHING = "clothing" - CLOTHING_SWIMWEAR = "clothing-swimwear" - DIGITAL_GOODS = "digital-goods" - DIGITAL_SERVICE = "digital-service" - DRUGS_NON_PRESCRIPTION = "drugs-non-prescription" - DRUGS_PRESCRIPTION = "drugs-prescription" - FOOD_BOTTLED_WATER = "food-bottled-water" - FOOD_CANDY = "food-candy" - FOOD_GROCERIES = "food-groceries" - FOOD_PREPARED = "food-prepared" - FOOD_SODA = "food-soda" - FOOD_SUPPLEMENTS = "food-supplements" - MAGAZINE_INDIVIDUAL = "magazine-individual" - MAGAZINE_SUBSCRIPTION = "magazine-subscription" - SERVICE_ADMISSION = "service-admission" - SERVICE_ADVERTISING = "service-advertising" - SERVICE_DRY_CLEANING = "service-dry-cleaning" - SERVICE_HAIRDRESSING = "service-hairdressing" - SERVICE_INSTALLATION = "service-installation" - SERVICE_MISCELLANEOUS = "service-miscellaneous" - SERVICE_PARKING = "service-parking" - SERVICE_PRINTING = "service-printing" - SERVICE_PROFESSIONAL = "service-professional" - SERVICE_REPAIR = "service-repair" - SERVICE_TRAINING = "service-training" - - def visit( - self, - standard_taxable: typing.Callable[[], T_Result], - standard_exempt: typing.Callable[[], T_Result], - books_religious: typing.Callable[[], T_Result], - books_textbook: typing.Callable[[], T_Result], - clothing: typing.Callable[[], T_Result], - clothing_swimwear: typing.Callable[[], T_Result], - digital_goods: typing.Callable[[], T_Result], - digital_service: typing.Callable[[], T_Result], - drugs_non_prescription: typing.Callable[[], T_Result], - drugs_prescription: typing.Callable[[], T_Result], - food_bottled_water: typing.Callable[[], T_Result], - food_candy: typing.Callable[[], T_Result], - food_groceries: typing.Callable[[], T_Result], - food_prepared: typing.Callable[[], T_Result], - food_soda: typing.Callable[[], T_Result], - food_supplements: typing.Callable[[], T_Result], - magazine_individual: typing.Callable[[], T_Result], - magazine_subscription: typing.Callable[[], T_Result], - service_admission: typing.Callable[[], T_Result], - service_advertising: typing.Callable[[], T_Result], - service_dry_cleaning: typing.Callable[[], T_Result], - service_hairdressing: typing.Callable[[], T_Result], - service_installation: typing.Callable[[], T_Result], - service_miscellaneous: typing.Callable[[], T_Result], - service_parking: typing.Callable[[], T_Result], - service_printing: typing.Callable[[], T_Result], - service_professional: typing.Callable[[], T_Result], - service_repair: typing.Callable[[], T_Result], - service_training: typing.Callable[[], T_Result], - ) -> T_Result: - if self is ProductSkuCreateProductFieldDataTaxCategory.STANDARD_TAXABLE: - return standard_taxable() - if self is ProductSkuCreateProductFieldDataTaxCategory.STANDARD_EXEMPT: - return standard_exempt() - if self is ProductSkuCreateProductFieldDataTaxCategory.BOOKS_RELIGIOUS: - return books_religious() - if self is ProductSkuCreateProductFieldDataTaxCategory.BOOKS_TEXTBOOK: - return books_textbook() - if self is ProductSkuCreateProductFieldDataTaxCategory.CLOTHING: - return clothing() - if self is ProductSkuCreateProductFieldDataTaxCategory.CLOTHING_SWIMWEAR: - return clothing_swimwear() - if self is ProductSkuCreateProductFieldDataTaxCategory.DIGITAL_GOODS: - return digital_goods() - if self is ProductSkuCreateProductFieldDataTaxCategory.DIGITAL_SERVICE: - return digital_service() - if self is ProductSkuCreateProductFieldDataTaxCategory.DRUGS_NON_PRESCRIPTION: - return drugs_non_prescription() - if self is ProductSkuCreateProductFieldDataTaxCategory.DRUGS_PRESCRIPTION: - return drugs_prescription() - if self is ProductSkuCreateProductFieldDataTaxCategory.FOOD_BOTTLED_WATER: - return food_bottled_water() - if self is ProductSkuCreateProductFieldDataTaxCategory.FOOD_CANDY: - return food_candy() - if self is ProductSkuCreateProductFieldDataTaxCategory.FOOD_GROCERIES: - return food_groceries() - if self is ProductSkuCreateProductFieldDataTaxCategory.FOOD_PREPARED: - return food_prepared() - if self is ProductSkuCreateProductFieldDataTaxCategory.FOOD_SODA: - return food_soda() - if self is ProductSkuCreateProductFieldDataTaxCategory.FOOD_SUPPLEMENTS: - return food_supplements() - if self is ProductSkuCreateProductFieldDataTaxCategory.MAGAZINE_INDIVIDUAL: - return magazine_individual() - if self is ProductSkuCreateProductFieldDataTaxCategory.MAGAZINE_SUBSCRIPTION: - return magazine_subscription() - if self is ProductSkuCreateProductFieldDataTaxCategory.SERVICE_ADMISSION: - return service_admission() - if self is ProductSkuCreateProductFieldDataTaxCategory.SERVICE_ADVERTISING: - return service_advertising() - if self is ProductSkuCreateProductFieldDataTaxCategory.SERVICE_DRY_CLEANING: - return service_dry_cleaning() - if self is ProductSkuCreateProductFieldDataTaxCategory.SERVICE_HAIRDRESSING: - return service_hairdressing() - if self is ProductSkuCreateProductFieldDataTaxCategory.SERVICE_INSTALLATION: - return service_installation() - if self is ProductSkuCreateProductFieldDataTaxCategory.SERVICE_MISCELLANEOUS: - return service_miscellaneous() - if self is ProductSkuCreateProductFieldDataTaxCategory.SERVICE_PARKING: - return service_parking() - if self is ProductSkuCreateProductFieldDataTaxCategory.SERVICE_PRINTING: - return service_printing() - if self is ProductSkuCreateProductFieldDataTaxCategory.SERVICE_PROFESSIONAL: - return service_professional() - if self is ProductSkuCreateProductFieldDataTaxCategory.SERVICE_REPAIR: - return service_repair() - if self is ProductSkuCreateProductFieldDataTaxCategory.SERVICE_TRAINING: - return service_training() diff --git a/src/webflow/resources/products/types/product_sku_create_sku.py b/src/webflow/resources/products/types/product_sku_create_sku.py deleted file mode 100644 index 2877e3c..0000000 --- a/src/webflow/resources/products/types/product_sku_create_sku.py +++ /dev/null @@ -1,46 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ....core.datetime_utils import serialize_datetime -from .product_sku_create_sku_field_data import ProductSkuCreateSkuFieldData - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class ProductSkuCreateSku(pydantic.BaseModel): - """ - The SKU object - """ - - id: typing.Optional[str] = pydantic.Field(default=None, description="Unique identifier for the Product") - last_published: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastPublished", default=None, description="The date the Product was last published" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="The date the Product was last updated" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The date the Product was created" - ) - field_data: typing.Optional[ProductSkuCreateSkuFieldData] = pydantic.Field( - alias="fieldData", default=None, description="Standard and Custom fields for a SKU" - ) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/products/types/product_sku_create_sku_field_data.py b/src/webflow/resources/products/types/product_sku_create_sku_field_data.py deleted file mode 100644 index 621cba9..0000000 --- a/src/webflow/resources/products/types/product_sku_create_sku_field_data.py +++ /dev/null @@ -1,62 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ....core.datetime_utils import serialize_datetime -from ....types.sku_value_list import SkuValueList -from .product_sku_create_sku_field_data_compare_at_price import ProductSkuCreateSkuFieldDataCompareAtPrice -from .product_sku_create_sku_field_data_ec_sku_billing_method import ProductSkuCreateSkuFieldDataEcSkuBillingMethod -from .product_sku_create_sku_field_data_ec_sku_subscription_plan import ( - ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlan, -) -from .product_sku_create_sku_field_data_price import ProductSkuCreateSkuFieldDataPrice - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class ProductSkuCreateSkuFieldData(pydantic.BaseModel): - """ - Standard and Custom fields for a SKU - """ - - sku_values: typing.Optional[SkuValueList] = pydantic.Field(alias="sku-values", default=None) - name: str = pydantic.Field(description="Name of the Product") - slug: str = pydantic.Field(description="URL structure of the Product in your site.") - price: ProductSkuCreateSkuFieldDataPrice = pydantic.Field(description="price of SKU") - compare_at_price: typing.Optional[ProductSkuCreateSkuFieldDataCompareAtPrice] = pydantic.Field( - alias="compare-at-price", default=None, description="comparison price of SKU" - ) - ec_sku_billing_method: typing.Optional[ProductSkuCreateSkuFieldDataEcSkuBillingMethod] = pydantic.Field( - alias="ec-sku-billing-method", default=None, description="The billing method for your SKU" - ) - ec_sku_subscription_plan: typing.Optional[ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlan] = pydantic.Field( - alias="ec-sku-subscription-plan", - default=None, - description="If your billing method is a Subscription Plan, outline the type and frequency of the subscription.", - ) - track_inventory: typing.Optional[bool] = pydantic.Field( - alias="track-inventory", - default=None, - description="A boolean indicating whether inventory for this product should be tracked.", - ) - quantity: typing.Optional[float] = pydantic.Field( - default=None, description="Quantity of SKU that will be tracked as items are ordered." - ) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/products/types/product_sku_create_sku_field_data_compare_at_price.py b/src/webflow/resources/products/types/product_sku_create_sku_field_data_compare_at_price.py deleted file mode 100644 index ea8c8b8..0000000 --- a/src/webflow/resources/products/types/product_sku_create_sku_field_data_compare_at_price.py +++ /dev/null @@ -1,33 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ....core.datetime_utils import serialize_datetime - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class ProductSkuCreateSkuFieldDataCompareAtPrice(pydantic.BaseModel): - """ - comparison price of SKU - """ - - value: typing.Optional[float] = pydantic.Field(default=None, description="Price of SKU") - unit: typing.Optional[str] = pydantic.Field(default=None, description="Currency of Item") - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_billing_method.py b/src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_billing_method.py deleted file mode 100644 index 9b4e545..0000000 --- a/src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_billing_method.py +++ /dev/null @@ -1,21 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import enum -import typing - -T_Result = typing.TypeVar("T_Result") - - -class ProductSkuCreateSkuFieldDataEcSkuBillingMethod(str, enum.Enum): - """ - The billing method for your SKU - """ - - ONE_TIME = "one-time" - SUBSCRIPTION = "subscription" - - def visit(self, one_time: typing.Callable[[], T_Result], subscription: typing.Callable[[], T_Result]) -> T_Result: - if self is ProductSkuCreateSkuFieldDataEcSkuBillingMethod.ONE_TIME: - return one_time() - if self is ProductSkuCreateSkuFieldDataEcSkuBillingMethod.SUBSCRIPTION: - return subscription() diff --git a/src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_subscription_plan.py b/src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_subscription_plan.py deleted file mode 100644 index 16df5eb..0000000 --- a/src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_subscription_plan.py +++ /dev/null @@ -1,39 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ....core.datetime_utils import serialize_datetime -from .product_sku_create_sku_field_data_ec_sku_subscription_plan_interval import ( - ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval, -) - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlan(pydantic.BaseModel): - """ - If your billing method is a Subscription Plan, outline the type and frequency of the subscription. - """ - - interval: typing.Optional[ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval] = pydantic.Field( - default=None, description="Interval of subscription renewal" - ) - frequency: typing.Optional[float] = pydantic.Field(default=None, description="Frequncy of billing within interval") - trial: typing.Optional[float] = pydantic.Field(default=None, description="Number of days of a trial") - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_subscription_plan_interval.py b/src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_subscription_plan_interval.py deleted file mode 100644 index 07093ba..0000000 --- a/src/webflow/resources/products/types/product_sku_create_sku_field_data_ec_sku_subscription_plan_interval.py +++ /dev/null @@ -1,33 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import enum -import typing - -T_Result = typing.TypeVar("T_Result") - - -class ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval(str, enum.Enum): - """ - Interval of subscription renewal - """ - - DAY = "day" - WEEK = "week" - MONTH = "month" - YEAR = "year" - - def visit( - self, - day: typing.Callable[[], T_Result], - week: typing.Callable[[], T_Result], - month: typing.Callable[[], T_Result], - year: typing.Callable[[], T_Result], - ) -> T_Result: - if self is ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval.DAY: - return day() - if self is ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval.WEEK: - return week() - if self is ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval.MONTH: - return month() - if self is ProductSkuCreateSkuFieldDataEcSkuSubscriptionPlanInterval.YEAR: - return year() diff --git a/src/webflow/resources/products/types/product_sku_create_sku_field_data_price.py b/src/webflow/resources/products/types/product_sku_create_sku_field_data_price.py deleted file mode 100644 index 9a430e4..0000000 --- a/src/webflow/resources/products/types/product_sku_create_sku_field_data_price.py +++ /dev/null @@ -1,34 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ....core.datetime_utils import serialize_datetime - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class ProductSkuCreateSkuFieldDataPrice(pydantic.BaseModel): - """ - price of SKU - """ - - required: typing.Optional[typing.Any] = None - value: typing.Optional[float] = pydantic.Field(default=None, description="Price of SKU") - unit: typing.Optional[str] = pydantic.Field(default=None, description="Currency of Item") - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/products/types/products_create_sku_response.py b/src/webflow/resources/products/types/products_create_sku_response.py index c176596..ddff764 100644 --- a/src/webflow/resources/products/types/products_create_sku_response.py +++ b/src/webflow/resources/products/types/products_create_sku_response.py @@ -4,15 +4,11 @@ import typing from ....core.datetime_utils import serialize_datetime +from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from ....types.sku import Sku -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class ProductsCreateSkuResponse(pydantic.BaseModel): +class ProductsCreateSkuResponse(pydantic_v1.BaseModel): skus: typing.Optional[typing.List[Sku]] = None def json(self, **kwargs: typing.Any) -> str: @@ -20,10 +16,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/scripts/client.py b/src/webflow/resources/scripts/client.py index dae0212..473d57e 100644 --- a/src/webflow/resources/scripts/client.py +++ b/src/webflow/resources/scripts/client.py @@ -1,27 +1,22 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.internal_server_error import InternalServerError from ...errors.not_found_error import NotFoundError from ...errors.too_many_requests_error import TooManyRequestsError from ...errors.unauthorized_error import UnauthorizedError -from ...types.custom_code_response import CustomCodeResponse +from ...types.custom_code_hosted_response import CustomCodeHostedResponse +from ...types.custom_code_inline_response import CustomCodeInlineResponse from ...types.registered_script_list import RegisteredScriptList -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -32,13 +27,23 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> RegisteredScriptList: """ - List of scripts registered to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets. Access to this endpoint requires a bearer token from a Data Client App.

Required scope | `custom_code:read` + List of scripts registered to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site - Parameters: - - site_id: str. Unique identifier for a Site + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + RegisteredScriptList + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -49,38 +54,21 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/registered_scripts" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/registered_scripts", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(RegisteredScriptList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(RegisteredScriptList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -92,29 +80,44 @@ def register_hosted( *, hosted_location: str, integrity_hash: str, - can_copy: typing.Optional[bool] = OMIT, version: str, display_name: str, + can_copy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CustomCodeResponse: + ) -> CustomCodeHostedResponse: """ - Add a script to a Site's Custom Code registry.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets. Access to this endpoint requires a bearer token from a Data Client App.

Required scope | `custom_code:write` + Add a script to a Site's Custom Code registry.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.


Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + hosted_location : str + URI for an externally hosted script location - Parameters: - - site_id: str. Unique identifier for a Site + integrity_hash : str + Sub-Resource Integrity Hash - - hosted_location: str. URI for an externally hosted script location + version : str + A Semantic Version (SemVer) string, denoting the version of the script - - integrity_hash: str. Sub-Resource Integrity Hash + display_name : str + User-facing name for the script. Must be between 1 and 50 alphanumeric characters - - can_copy: typing.Optional[bool]. Define whether the script can be copied on site duplication and transfer + can_copy : typing.Optional[bool] + Define whether the script can be copied on site duplication and transfer - - version: str. A Semantic Version (SemVer) string, denoting the version of the script + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - display_name: str. User-facing name for the script + Returns + ------- + CustomCodeHostedResponse + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -128,54 +131,32 @@ def register_hosted( display_name="displayName", ) """ - _request: typing.Dict[str, typing.Any] = { - "hostedLocation": hosted_location, - "integrityHash": integrity_hash, - "version": version, - "displayName": display_name, - } - if can_copy is not OMIT: - _request["canCopy"] = can_copy _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", + method="POST", + json={ + "hostedLocation": hosted_location, + "integrityHash": integrity_hash, + "canCopy": can_copy, + "version": version, + "displayName": display_name, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CustomCodeResponse, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CustomCodeHostedResponse, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -186,30 +167,45 @@ def register_inline( site_id: str, *, source_code: str, - integrity_hash: typing.Optional[str] = OMIT, - can_copy: typing.Optional[bool] = OMIT, version: str, display_name: str, + integrity_hash: typing.Optional[str] = OMIT, + can_copy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CustomCodeResponse: + ) -> CustomCodeInlineResponse: """ - Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:write` + Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + source_code : str + The code to be added to the site (to be hosted by Webflow). - Parameters: - - site_id: str. Unique identifier for a Site + version : str + A Semantic Version (SemVer) string, denoting the version of the script - - source_code: str. The code to be added to the site (to be hosted by Webflow). + display_name : str + User-facing name for the script. Must be between 1 and 50 alphanumeric characters - - integrity_hash: typing.Optional[str]. Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) + integrity_hash : typing.Optional[str] + Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) - - can_copy: typing.Optional[bool]. Define whether the script can be copied on site duplication and transfer + can_copy : typing.Optional[bool] + Define whether the script can be copied on site duplication and transfer - - version: str. A Semantic Version (SemVer) string, denoting the version of the script + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - display_name: str. User-facing name for the script + Returns + ------- + CustomCodeInlineResponse + Created - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -222,55 +218,32 @@ def register_inline( display_name="Alert", ) """ - _request: typing.Dict[str, typing.Any] = { - "sourceCode": source_code, - "version": version, - "displayName": display_name, - } - if integrity_hash is not OMIT: - _request["integrityHash"] = integrity_hash - if can_copy is not OMIT: - _request["canCopy"] = can_copy _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", + method="POST", + json={ + "sourceCode": source_code, + "integrityHash": integrity_hash, + "canCopy": can_copy, + "version": version, + "displayName": display_name, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CustomCodeResponse, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CustomCodeInlineResponse, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -285,13 +258,23 @@ async def list( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> RegisteredScriptList: """ - List of scripts registered to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets. Access to this endpoint requires a bearer token from a Data Client App.

Required scope | `custom_code:read` + List of scripts registered to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + RegisteredScriptList + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -302,38 +285,21 @@ async def list( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/registered_scripts" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/registered_scripts", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(RegisteredScriptList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(RegisteredScriptList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -345,29 +311,44 @@ async def register_hosted( *, hosted_location: str, integrity_hash: str, - can_copy: typing.Optional[bool] = OMIT, version: str, display_name: str, + can_copy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CustomCodeResponse: + ) -> CustomCodeHostedResponse: """ - Add a script to a Site's Custom Code registry.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets. Access to this endpoint requires a bearer token from a Data Client App.

Required scope | `custom_code:write` + Add a script to a Site's Custom Code registry.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.


Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + hosted_location : str + URI for an externally hosted script location - Parameters: - - site_id: str. Unique identifier for a Site + integrity_hash : str + Sub-Resource Integrity Hash - - hosted_location: str. URI for an externally hosted script location + version : str + A Semantic Version (SemVer) string, denoting the version of the script - - integrity_hash: str. Sub-Resource Integrity Hash + display_name : str + User-facing name for the script. Must be between 1 and 50 alphanumeric characters - - can_copy: typing.Optional[bool]. Define whether the script can be copied on site duplication and transfer + can_copy : typing.Optional[bool] + Define whether the script can be copied on site duplication and transfer - - version: str. A Semantic Version (SemVer) string, denoting the version of the script + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - display_name: str. User-facing name for the script + Returns + ------- + CustomCodeHostedResponse + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -381,54 +362,32 @@ async def register_hosted( display_name="displayName", ) """ - _request: typing.Dict[str, typing.Any] = { - "hostedLocation": hosted_location, - "integrityHash": integrity_hash, - "version": version, - "displayName": display_name, - } - if can_copy is not OMIT: - _request["canCopy"] = can_copy _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", + method="POST", + json={ + "hostedLocation": hosted_location, + "integrityHash": integrity_hash, + "canCopy": can_copy, + "version": version, + "displayName": display_name, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CustomCodeResponse, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CustomCodeHostedResponse, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -439,30 +398,45 @@ async def register_inline( site_id: str, *, source_code: str, - integrity_hash: typing.Optional[str] = OMIT, - can_copy: typing.Optional[bool] = OMIT, version: str, display_name: str, + integrity_hash: typing.Optional[str] = OMIT, + can_copy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CustomCodeResponse: + ) -> CustomCodeInlineResponse: """ - Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:write` + Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + source_code : str + The code to be added to the site (to be hosted by Webflow). - Parameters: - - site_id: str. Unique identifier for a Site + version : str + A Semantic Version (SemVer) string, denoting the version of the script - - source_code: str. The code to be added to the site (to be hosted by Webflow). + display_name : str + User-facing name for the script. Must be between 1 and 50 alphanumeric characters - - integrity_hash: typing.Optional[str]. Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) + integrity_hash : typing.Optional[str] + Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) - - can_copy: typing.Optional[bool]. Define whether the script can be copied on site duplication and transfer + can_copy : typing.Optional[bool] + Define whether the script can be copied on site duplication and transfer - - version: str. A Semantic Version (SemVer) string, denoting the version of the script + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - display_name: str. User-facing name for the script + Returns + ------- + CustomCodeInlineResponse + Created - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -475,55 +449,32 @@ async def register_inline( display_name="Alert", ) """ - _request: typing.Dict[str, typing.Any] = { - "sourceCode": source_code, - "version": version, - "displayName": display_name, - } - if integrity_hash is not OMIT: - _request["integrityHash"] = integrity_hash - if can_copy is not OMIT: - _request["canCopy"] = can_copy _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), + f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", + method="POST", + json={ + "sourceCode": source_code, + "integrityHash": integrity_hash, + "canCopy": can_copy, + "version": version, + "displayName": display_name, }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(CustomCodeResponse, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(CustomCodeInlineResponse, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/sites/client.py b/src/webflow/resources/sites/client.py index ee321fe..24b355d 100644 --- a/src/webflow/resources/sites/client.py +++ b/src/webflow/resources/sites/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.forbidden_error import ForbiddenError @@ -17,14 +16,10 @@ from ...errors.unauthorized_error import UnauthorizedError from ...types.domains import Domains from ...types.site import Site +from ...types.sites import Sites from .resources.activity_logs.client import ActivityLogsClient, AsyncActivityLogsClient from .resources.scripts.client import AsyncScriptsClient, ScriptsClient -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -35,13 +30,22 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): self.activity_logs = ActivityLogsClient(client_wrapper=self._client_wrapper) self.scripts = ScriptsClient(client_wrapper=self._client_wrapper) - def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Site: + def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Sites: """ List of all sites the provided access token is able to access.

Required scope | `sites:read` - Parameters: - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Sites + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -49,37 +53,20 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Si ) client.sites.list() """ - _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "sites"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, - ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Site, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore + _response = self._client_wrapper.httpx_client.request("sites", method="GET", request_options=request_options) try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Sites, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -89,11 +76,21 @@ def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ Get a site by site id

Required scope | `sites:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Site + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -104,36 +101,21 @@ def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Site, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Site, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -143,11 +125,21 @@ def get_custom_domain(self, site_id: str, *, request_options: typing.Optional[Re """ Get a list of all custom domains related to site.

Required scope | `sites:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Domains + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -158,38 +150,21 @@ def get_custom_domain(self, site_id: str, *, request_options: typing.Optional[Re ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/custom_domains" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/custom_domains", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Domains, _response.json()) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Domains, _response.json()) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -206,15 +181,26 @@ def publish( """ Publish a site to one more more domains.

Required scope | `sites:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + custom_domains : typing.Optional[typing.Sequence[str]] + Array of Custom Domain ids to publish - - custom_domains: typing.Optional[typing.Sequence[str]]. Array of Custom Domain ids to publish + publish_to_webflow_subdomain : typing.Optional[bool] + Choice of whether to publish to the default Webflow Subdomain - - publish_to_webflow_subdomain: typing.Optional[bool]. Choice of whether to publish to the default Webflow Subdomain + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + None + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -222,53 +208,28 @@ def publish( ) client.sites.publish( site_id="site_id", - publish_to_webflow_subdomain=False, ) """ - _request: typing.Dict[str, typing.Any] = {} - if custom_domains is not OMIT: - _request["customDomains"] = custom_domains - if publish_to_webflow_subdomain is not OMIT: - _request["publishToWebflowSubdomain"] = publish_to_webflow_subdomain _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/publish" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/publish", + method="POST", + json={"customDomains": custom_domains, "publishToWebflowSubdomain": publish_to_webflow_subdomain}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -281,13 +242,22 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): self.activity_logs = AsyncActivityLogsClient(client_wrapper=self._client_wrapper) self.scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) - async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Site: + async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Sites: """ List of all sites the provided access token is able to access.

Required scope | `sites:read` - Parameters: - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Sites + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -296,36 +266,21 @@ async def list(self, *, request_options: typing.Optional[RequestOptions] = None) await client.sites.list() """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "sites"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + "sites", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Site, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Sites, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -335,11 +290,21 @@ async def get(self, site_id: str, *, request_options: typing.Optional[RequestOpt """ Get a site by site id

Required scope | `sites:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Site + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -350,36 +315,21 @@ async def get(self, site_id: str, *, request_options: typing.Optional[RequestOpt ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Site, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Site, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -391,11 +341,21 @@ async def get_custom_domain( """ Get a list of all custom domains related to site.

Required scope | `sites:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Domains + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -406,38 +366,21 @@ async def get_custom_domain( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/custom_domains" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/custom_domains", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Domains, _response.json()) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Domains, _response.json()) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -454,15 +397,26 @@ async def publish( """ Publish a site to one more more domains.

Required scope | `sites:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + custom_domains : typing.Optional[typing.Sequence[str]] + Array of Custom Domain ids to publish + + publish_to_webflow_subdomain : typing.Optional[bool] + Choice of whether to publish to the default Webflow Subdomain - - custom_domains: typing.Optional[typing.Sequence[str]]. Array of Custom Domain ids to publish + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - publish_to_webflow_subdomain: typing.Optional[bool]. Choice of whether to publish to the default Webflow Subdomain + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -470,53 +424,28 @@ async def publish( ) await client.sites.publish( site_id="site_id", - publish_to_webflow_subdomain=False, ) """ - _request: typing.Dict[str, typing.Any] = {} - if custom_domains is not OMIT: - _request["customDomains"] = custom_domains - if publish_to_webflow_subdomain is not OMIT: - _request["publishToWebflowSubdomain"] = publish_to_webflow_subdomain _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/publish" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/publish", + method="POST", + json={"customDomains": custom_domains, "publishToWebflowSubdomain": publish_to_webflow_subdomain}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/sites/resources/activity_logs/client.py b/src/webflow/resources/sites/resources/activity_logs/client.py index a0edffd..63571d4 100644 --- a/src/webflow/resources/sites/resources/activity_logs/client.py +++ b/src/webflow/resources/sites/resources/activity_logs/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from .....core.api_error import ApiError from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.jsonable_encoder import jsonable_encoder -from .....core.remove_none_from_dict import remove_none_from_dict +from .....core.pydantic_utilities import pydantic_v1 from .....core.request_options import RequestOptions from .....errors.forbidden_error import ForbiddenError from .....errors.internal_server_error import InternalServerError @@ -15,11 +14,6 @@ from .....errors.too_many_requests_error import TooManyRequestsError from .....types.site_activity_log_response import SiteActivityLogResponse -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - class ActivityLogsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): @@ -36,15 +30,27 @@ def list( """ Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + Returns + ------- + SiteActivityLogResponse + A list of site activity logs - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -55,46 +61,22 @@ def list( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/activity_logs" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "limit": limit, - "offset": offset, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/activity_logs", + method="GET", + params={"limit": limit, "offset": offset}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(SiteActivityLogResponse, _response.json()) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(SiteActivityLogResponse, _response.json()) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -116,15 +98,27 @@ async def list( """ Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + Returns + ------- + SiteActivityLogResponse + A list of site activity logs - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -135,46 +129,22 @@ async def list( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/activity_logs" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "limit": limit, - "offset": offset, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/activity_logs", + method="GET", + params={"limit": limit, "offset": offset}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(SiteActivityLogResponse, _response.json()) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(SiteActivityLogResponse, _response.json()) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/sites/resources/scripts/client.py b/src/webflow/resources/sites/resources/scripts/client.py index bca1824..9470804 100644 --- a/src/webflow/resources/sites/resources/scripts/client.py +++ b/src/webflow/resources/sites/resources/scripts/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from .....core.api_error import ApiError from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.jsonable_encoder import jsonable_encoder -from .....core.remove_none_from_dict import remove_none_from_dict +from .....core.pydantic_utilities import pydantic_v1 from .....core.request_options import RequestOptions from .....errors.bad_request_error import BadRequestError from .....errors.internal_server_error import InternalServerError @@ -15,13 +14,9 @@ from .....errors.too_many_requests_error import TooManyRequestsError from .....errors.unauthorized_error import UnauthorizedError from .....types.list_custom_code_blocks import ListCustomCodeBlocks +from .....types.script_apply import ScriptApply from .....types.script_apply_list import ScriptApplyList -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -34,13 +29,23 @@ def get_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Site.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:read` + Get all registered scripts that have been applied to a specific Site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site - Parameters: - - site_id: str. Unique identifier for a Site + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + ScriptApplyList + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -51,57 +56,63 @@ def get_custom_code( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/custom_code", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) def upsert_custom_code( - self, site_id: str, *, request: ScriptApplyList, request_options: typing.Optional[RequestOptions] = None + self, + site_id: str, + *, + scripts: typing.Optional[typing.Sequence[ScriptApply]] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:write` + Add a registered script to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site - Parameters: - - site_id: str. Unique identifier for a Site + scripts : typing.Optional[typing.Sequence[ScriptApply]] + A list of scripts applied to a Site or a Page - - request: ScriptApplyList. + last_updated : typing.Optional[str] + Date when the Site's scripts were last updated - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import ScriptApply, ScriptApplyList, ScriptApplyLocation + created_on : typing.Optional[str] + Date when the Site's scripts were created + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ScriptApplyList + Request was successful + + Examples + -------- + from webflow import ScriptApply, ScriptApplyLocation from webflow.client import Webflow client = Webflow( @@ -109,67 +120,41 @@ def upsert_custom_code( ) client.sites.scripts.upsert_custom_code( site_id="site_id", - request=ScriptApplyList( - scripts=[ - ScriptApply( - id="cms_slider", - location=ScriptApplyLocation.HEADER, - version="1.0.0", - attributes={"my-attribute": "some-value"}, - ), - ScriptApply( - id="alert", - location=ScriptApplyLocation.HEADER, - version="0.0.1", - ), - ScriptApply( - id="id", - location=ScriptApplyLocation.HEADER, - version="version", - ), - ], - ), + scripts=[ + ScriptApply( + id="cms_slider", + location=ScriptApplyLocation.HEADER, + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location=ScriptApplyLocation.HEADER, + version="0.0.1", + ), + ], ) """ _response = self._client_wrapper.httpx_client.request( - "PUT", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/custom_code", + method="PUT", + json={"scripts": scripts, "lastUpdated": last_updated, "createdOn": created_on}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -177,13 +162,22 @@ def upsert_custom_code( def delete_custom_code(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete the custom code block that an app created for a Site

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:write` + Delete the custom code block that an app created for a Site

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site - Parameters: - - site_id: str. Unique identifier for a Site + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + None + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -194,38 +188,21 @@ def delete_custom_code(self, site_id: str, *, request_options: typing.Optional[R ) """ _response = self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/custom_code", method="DELETE", request_options=request_options ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -240,17 +217,29 @@ def list_custom_code_blocks( request_options: typing.Optional[RequestOptions] = None, ) -> ListCustomCodeBlocks: """ - Get all instances of Custom Code applied to a Site or Pages.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:read` + Get all instances of Custom Code applied to a Site or Pages.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - Parameters: - - site_id: str. Unique identifier for a Site + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + Returns + ------- + ListCustomCodeBlocks + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -261,48 +250,24 @@ def list_custom_code_blocks( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/custom_code/blocks" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "offset": offset, - "limit": limit, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", + method="GET", + params={"offset": offset, "limit": limit}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ListCustomCodeBlocks, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ListCustomCodeBlocks, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -317,13 +282,23 @@ async def get_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Site.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:read` + Get all registered scripts that have been applied to a specific Site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ScriptApplyList + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -334,57 +309,63 @@ async def get_custom_code( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/custom_code", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) async def upsert_custom_code( - self, site_id: str, *, request: ScriptApplyList, request_options: typing.Optional[RequestOptions] = None + self, + site_id: str, + *, + scripts: typing.Optional[typing.Sequence[ScriptApply]] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:write` + Add a registered script to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site - Parameters: - - site_id: str. Unique identifier for a Site + scripts : typing.Optional[typing.Sequence[ScriptApply]] + A list of scripts applied to a Site or a Page - - request: ScriptApplyList. + last_updated : typing.Optional[str] + Date when the Site's scripts were last updated - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- - from webflow import ScriptApply, ScriptApplyList, ScriptApplyLocation + created_on : typing.Optional[str] + Date when the Site's scripts were created + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ScriptApplyList + Request was successful + + Examples + -------- + from webflow import ScriptApply, ScriptApplyLocation from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -392,67 +373,41 @@ async def upsert_custom_code( ) await client.sites.scripts.upsert_custom_code( site_id="site_id", - request=ScriptApplyList( - scripts=[ - ScriptApply( - id="cms_slider", - location=ScriptApplyLocation.HEADER, - version="1.0.0", - attributes={"my-attribute": "some-value"}, - ), - ScriptApply( - id="alert", - location=ScriptApplyLocation.HEADER, - version="0.0.1", - ), - ScriptApply( - id="id", - location=ScriptApplyLocation.HEADER, - version="version", - ), - ], - ), + scripts=[ + ScriptApply( + id="cms_slider", + location=ScriptApplyLocation.HEADER, + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location=ScriptApplyLocation.HEADER, + version="0.0.1", + ), + ], ) """ _response = await self._client_wrapper.httpx_client.request( - "PUT", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/custom_code", + method="PUT", + json={"scripts": scripts, "lastUpdated": last_updated, "createdOn": created_on}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -462,13 +417,22 @@ async def delete_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> None: """ - Delete the custom code block that an app created for a Site

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:write` + Delete the custom code block that an app created for a Site

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site - Parameters: - - site_id: str. Unique identifier for a Site + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + None + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -479,38 +443,21 @@ async def delete_custom_code( ) """ _response = await self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/custom_code" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/custom_code", method="DELETE", request_options=request_options ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -525,17 +472,29 @@ async def list_custom_code_blocks( request_options: typing.Optional[RequestOptions] = None, ) -> ListCustomCodeBlocks: """ - Get all instances of Custom Code applied to a Site or Pages.

Access to this endpoint requires a bearer token from a Data Client App. Required scope | `custom_code:read` + Get all instances of Custom Code applied to a Site or Pages.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - Parameters: - - site_id: str. Unique identifier for a Site + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + Returns + ------- + ListCustomCodeBlocks + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -546,48 +505,24 @@ async def list_custom_code_blocks( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/custom_code/blocks" - ), - params=jsonable_encoder( - remove_none_from_dict( - { - "offset": offset, - "limit": limit, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", + method="GET", + params={"offset": offset, "limit": limit}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(ListCustomCodeBlocks, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(ListCustomCodeBlocks, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/token/client.py b/src/webflow/resources/token/client.py index 9236d46..19a9083 100644 --- a/src/webflow/resources/token/client.py +++ b/src/webflow/resources/token/client.py @@ -1,24 +1,17 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.forbidden_error import ForbiddenError from ...errors.unauthorized_error import UnauthorizedError from ...types.authorization import Authorization from ...types.authorized_user import AuthorizedUser -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - class TokenClient: def __init__(self, *, client_wrapper: SyncClientWrapper): @@ -28,9 +21,18 @@ def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = No """ Information about the Authorized User

Required Scope | `authorized_user:read` - Parameters: - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AuthorizedUser + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -39,30 +41,15 @@ def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = No client.token.authorized_by() """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "token/authorized_by"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + "token/authorized_by", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AuthorizedUser, _response.json()) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AuthorizedUser, _response.json()) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -70,11 +57,20 @@ def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = No def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) -> Authorization: """ - Information about the authorization token

Access to this endpoint requires a bearer token from a Data Client App. + Information about the authorization token
Access to this endpoint requires a bearer token from a Data Client App.
+ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Authorization + Request was successful - Parameters: - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -83,28 +79,13 @@ def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) client.token.introspect() """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "token/introspect"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + "token/introspect", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Authorization, _response.json()) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Authorization, _response.json()) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -119,9 +100,18 @@ async def authorized_by(self, *, request_options: typing.Optional[RequestOptions """ Information about the Authorized User

Required Scope | `authorized_user:read` - Parameters: - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AuthorizedUser + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -130,30 +120,15 @@ async def authorized_by(self, *, request_options: typing.Optional[RequestOptions await client.token.authorized_by() """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "token/authorized_by"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + "token/authorized_by", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(AuthorizedUser, _response.json()) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(AuthorizedUser, _response.json()) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -161,11 +136,20 @@ async def authorized_by(self, *, request_options: typing.Optional[RequestOptions async def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) -> Authorization: """ - Information about the authorization token

Access to this endpoint requires a bearer token from a Data Client App. + Information about the authorization token
Access to this endpoint requires a bearer token from a Data Client App.
+ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Authorization + Request was successful - Parameters: - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -174,28 +158,13 @@ async def introspect(self, *, request_options: typing.Optional[RequestOptions] = await client.token.introspect() """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", "token/introspect"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + "token/introspect", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Authorization, _response.json()) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Authorization, _response.json()) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/users/client.py b/src/webflow/resources/users/client.py index f3d62bf..08e8045 100644 --- a/src/webflow/resources/users/client.py +++ b/src/webflow/resources/users/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.conflict_error import ConflictError @@ -21,11 +20,6 @@ from .types.users_list_request_sort import UsersListRequestSort from .types.users_update_request_data import UsersUpdateRequestData -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -46,20 +40,34 @@ def list( """ Get a list of users for a site

Required scope | `users:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + sort : typing.Optional[UsersListRequestSort] + Sort string to use when ordering users - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) - - sort: typing.Optional[UsersListRequestSort]. Sort string to use when ordering users + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). + Returns + ------- + UserList + Request was successful - Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -70,49 +78,26 @@ def list( ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/users"), - params=jsonable_encoder( - remove_none_from_dict( - { - "offset": offset, - "limit": limit, - "sort": sort, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/users", + method="GET", + params={"offset": offset, "limit": limit, "sort": sort}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(UserList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(UserList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -122,13 +107,24 @@ def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[Re """ Get a User by ID

Required scope | `users:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + user_id : str + Unique identifier for a User - - user_id: str. Unique identifier for a User + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + User + Request was successful + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -140,41 +136,25 @@ def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[Re ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + method="GET", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(User, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -184,13 +164,23 @@ def delete(self, site_id: str, user_id: str, *, request_options: typing.Optional """ Delete a User by ID

Required scope | `users:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - user_id: str. Unique identifier for a User + user_id : str + Unique identifier for a User - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -202,41 +192,25 @@ def delete(self, site_id: str, user_id: str, *, request_options: typing.Optional ) """ _response = self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + method="DELETE", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -256,17 +230,30 @@ def update( - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + user_id : str + Unique identifier for a User + + data : typing.Optional[UsersUpdateRequestData] - - user_id: str. Unique identifier for a User + access_groups : typing.Optional[typing.Sequence[str]] + An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. - - data: typing.Optional[UsersUpdateRequestData]. - - access_groups: typing.Optional[typing.Sequence[str]]. An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + User + Request was successful + + Examples + -------- from webflow import UsersUpdateRequestData from webflow.client import Webflow @@ -281,56 +268,31 @@ def update( accept_privacy=False, accept_communications=False, ), - access_groups=["webflowers", "platinum", "free-tier", "accessGroups"], + access_groups=["webflowers", "platinum", "free-tier"], ) """ - _request: typing.Dict[str, typing.Any] = {} - if data is not OMIT: - _request["data"] = data - if access_groups is not OMIT: - _request["accessGroups"] = access_groups _response = self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + method="PATCH", + json={"data": data, "accessGroups": access_groups}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(User, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -347,15 +309,28 @@ def invite( """ Create and invite a user with an email address. The user will be sent and invite via email, which they will need to accept in order to join paid Access Groups.

Required scope | `users:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + email : str + Email address of user to send invite to + + access_groups : typing.Optional[typing.Sequence[str]] + An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. + - - email: str. Email address of user to send invite to + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - access_groups: typing.Optional[typing.Sequence[str]]. An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. + Returns + ------- + User + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -364,55 +339,33 @@ def invite( client.users.invite( site_id="site_id", email="some.one@home.com", - access_groups=["webflowers", "accessGroups"], + access_groups=["webflowers"], ) """ - _request: typing.Dict[str, typing.Any] = {"email": email} - if access_groups is not OMIT: - _request["accessGroups"] = access_groups _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/users/invite" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/users/invite", + method="POST", + json={"email": email, "accessGroups": access_groups}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(User, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -435,20 +388,34 @@ async def list( """ Get a list of users for a site

Required scope | `users:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - offset: typing.Optional[float]. Offset used for pagination if the results have more than limit records + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - - limit: typing.Optional[float]. Maximum number of records to be returned (max limit: 100) + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) - - sort: typing.Optional[UsersListRequestSort]. Sort string to use when ordering users + sort : typing.Optional[UsersListRequestSort] + Sort string to use when ordering users - Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). + Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). - Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + UserList + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -459,49 +426,26 @@ async def list( ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/users"), - params=jsonable_encoder( - remove_none_from_dict( - { - "offset": offset, - "limit": limit, - "sort": sort, - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - } - ) - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/users", + method="GET", + params={"offset": offset, "limit": limit, "sort": sort}, + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(UserList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(UserList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -511,13 +455,24 @@ async def get(self, site_id: str, user_id: str, *, request_options: typing.Optio """ Get a User by ID

Required scope | `users:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + user_id : str + Unique identifier for a User + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - user_id: str. Unique identifier for a User + Returns + ------- + User + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -529,41 +484,25 @@ async def get(self, site_id: str, user_id: str, *, request_options: typing.Optio ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + method="GET", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(User, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -575,13 +514,23 @@ async def delete( """ Delete a User by ID

Required scope | `users:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + user_id : str + Unique identifier for a User - - user_id: str. Unique identifier for a User + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + None + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -593,41 +542,25 @@ async def delete( ) """ _response = await self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + method="DELETE", + request_options=request_options, ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -647,17 +580,30 @@ async def update( - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + user_id : str + Unique identifier for a User + + data : typing.Optional[UsersUpdateRequestData] + + access_groups : typing.Optional[typing.Sequence[str]] + An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. - - user_id: str. Unique identifier for a User - - data: typing.Optional[UsersUpdateRequestData]. + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - access_groups: typing.Optional[typing.Sequence[str]]. An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. + Returns + ------- + User + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow import UsersUpdateRequestData from webflow.client import AsyncWebflow @@ -672,56 +618,31 @@ async def update( accept_privacy=False, accept_communications=False, ), - access_groups=["webflowers", "platinum", "free-tier", "accessGroups"], + access_groups=["webflowers", "platinum", "free-tier"], ) """ - _request: typing.Dict[str, typing.Any] = {} - if data is not OMIT: - _request["data"] = data - if access_groups is not OMIT: - _request["accessGroups"] = access_groups _response = await self._client_wrapper.httpx_client.request( - "PATCH", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + method="PATCH", + json={"data": data, "accessGroups": access_groups}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(User, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -738,15 +659,28 @@ async def invite( """ Create and invite a user with an email address. The user will be sent and invite via email, which they will need to accept in order to join paid Access Groups.

Required scope | `users:write` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - email: str. Email address of user to send invite to + email : str + Email address of user to send invite to - - access_groups: typing.Optional[typing.Sequence[str]]. An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. + access_groups : typing.Optional[typing.Sequence[str]] + An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + User + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -755,55 +689,33 @@ async def invite( await client.users.invite( site_id="site_id", email="some.one@home.com", - access_groups=["webflowers", "accessGroups"], + access_groups=["webflowers"], ) """ - _request: typing.Dict[str, typing.Any] = {"email": email} - if access_groups is not OMIT: - _request["accessGroups"] = access_groups _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/users/invite" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/users/invite", + method="POST", + json={"email": email, "accessGroups": access_groups}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(User, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 403: - raise ForbiddenError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 409: - raise ConflictError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 403: + raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 409: + raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/users/types/users_update_request_data.py b/src/webflow/resources/users/types/users_update_request_data.py index cb99ef6..c765cea 100644 --- a/src/webflow/resources/users/types/users_update_request_data.py +++ b/src/webflow/resources/users/types/users_update_request_data.py @@ -4,36 +4,41 @@ import typing from ....core.datetime_utils import serialize_datetime +from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class UsersUpdateRequestData(pydantic.BaseModel): - name: typing.Optional[str] = pydantic.Field(default=None, description="The name of the user") - accept_privacy: typing.Optional[bool] = pydantic.Field( - alias="accept-privacy", - default=None, - description="Boolean indicating if the user has accepted the privacy policy", - ) - accept_communications: typing.Optional[bool] = pydantic.Field( - alias="accept-communications", - default=None, - description="Boolean indicating if the user has accepted to receive communications", - ) + +class UsersUpdateRequestData(pydantic_v1.BaseModel): + name: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The name of the user + """ + + accept_privacy: typing.Optional[bool] = pydantic_v1.Field(alias="accept-privacy", default=None) + """ + Boolean indicating if the user has accepted the privacy policy + """ + + accept_communications: typing.Optional[bool] = pydantic_v1.Field(alias="accept-communications", default=None) + """ + Boolean indicating if the user has accepted to receive communications + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/webhooks/client.py b/src/webflow/resources/webhooks/client.py index 0309b13..9225c18 100644 --- a/src/webflow/resources/webhooks/client.py +++ b/src/webflow/resources/webhooks/client.py @@ -1,13 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -import urllib.parse from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.jsonable_encoder import jsonable_encoder -from ...core.remove_none_from_dict import remove_none_from_dict +from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions from ...errors.bad_request_error import BadRequestError from ...errors.internal_server_error import InternalServerError @@ -18,11 +17,6 @@ from ...types.webhook import Webhook from ...types.webhook_list import WebhookList -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -35,11 +29,21 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ List all App-created Webhooks registered for a given site

Required scope | `sites:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WebhookList + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -50,38 +54,21 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/webhooks" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/webhooks", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(WebhookList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(WebhookList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -97,20 +84,34 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> Webhook: """ - Create a new Webhook, to be notified when Webflow resources change. Limit of 75 registrations per `triggerType`, per site.

Access to this endpoint requires a bearer token from a Data Client App. The only exceptions are for creating webhooks with `site_publish` or `form_submission` triggers, which can be done with Site Tokens
Required scope | `sites:write` + Create a new Webhook, to be notified when Webflow resources change. Limit of 75 registrations per `triggerType`, per site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + trigger_type : TriggerType + + url : str + The server URI that Webflow will call when your Webhook is triggered - Parameters: - - site_id: str. Unique identifier for a Site - - trigger_type: TriggerType. + filter : typing.Optional[typing.Dict[str, typing.Any]] + Filter for selecting which events you want Webhooks to be triggered for. + ** Only available for `form_submission` trigger types. ** - - url: str. The server URI that Webflow will call when your Webhook is triggered - - filter: typing.Optional[typing.Dict[str, typing.Any]]. Filter for selecting which events you want Webhooks to be triggered for. - ** Only available for `form_submission` trigger types. ** + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Webhook + Request was successful + + Examples + -------- from webflow import TriggerType from webflow.client import Webflow @@ -123,48 +124,26 @@ def create( url="https://api.mydomain.com/webhook", ) """ - _request: typing.Dict[str, typing.Any] = {"triggerType": trigger_type, "url": url} - if filter is not OMIT: - _request["filter"] = filter _response = self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/webhooks" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/webhooks", + method="POST", + json={"triggerType": trigger_type, "url": url, "filter": filter}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Webhook, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Webhook, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -174,11 +153,21 @@ def get(self, webhook_id: str, *, request_options: typing.Optional[RequestOption """ Get a specific Webhook instance - Parameters: - - webhook_id: str. Unique identifier for a Webhook + Parameters + ---------- + webhook_id : str + Unique identifier for a Webhook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Webhook + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -189,36 +178,21 @@ def get(self, webhook_id: str, *, request_options: typing.Optional[RequestOption ) """ _response = self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"webhooks/{jsonable_encoder(webhook_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"webhooks/{jsonable_encoder(webhook_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Webhook, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Webhook, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -228,11 +202,20 @@ def delete(self, webhook_id: str, *, request_options: typing.Optional[RequestOpt """ Remove a Webhook - Parameters: - - webhook_id: str. Unique identifier for a Webhook + Parameters + ---------- + webhook_id : str + Unique identifier for a Webhook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import Webflow client = Webflow( @@ -243,36 +226,21 @@ def delete(self, webhook_id: str, *, request_options: typing.Optional[RequestOpt ) """ _response = self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"webhooks/{jsonable_encoder(webhook_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"webhooks/{jsonable_encoder(webhook_id)}", method="DELETE", request_options=request_options ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -287,11 +255,21 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp """ List all App-created Webhooks registered for a given site

Required scope | `sites:read` - Parameters: - - site_id: str. Unique identifier for a Site + Parameters + ---------- + site_id : str + Unique identifier for a Site - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + WebhookList + Request was successful + + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -302,38 +280,21 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/webhooks" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/webhooks", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(WebhookList, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(WebhookList, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -349,20 +310,34 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> Webhook: """ - Create a new Webhook, to be notified when Webflow resources change. Limit of 75 registrations per `triggerType`, per site.

Access to this endpoint requires a bearer token from a Data Client App. The only exceptions are for creating webhooks with `site_publish` or `form_submission` triggers, which can be done with Site Tokens
Required scope | `sites:write` + Create a new Webhook, to be notified when Webflow resources change. Limit of 75 registrations per `triggerType`, per site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + trigger_type : TriggerType + + url : str + The server URI that Webflow will call when your Webhook is triggered - Parameters: - - site_id: str. Unique identifier for a Site - - trigger_type: TriggerType. + filter : typing.Optional[typing.Dict[str, typing.Any]] + Filter for selecting which events you want Webhooks to be triggered for. + ** Only available for `form_submission` trigger types. ** - - url: str. The server URI that Webflow will call when your Webhook is triggered - - filter: typing.Optional[typing.Dict[str, typing.Any]]. Filter for selecting which events you want Webhooks to be triggered for. - ** Only available for `form_submission` trigger types. ** + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Returns + ------- + Webhook + Request was successful + + Examples + -------- from webflow import TriggerType from webflow.client import AsyncWebflow @@ -375,48 +350,26 @@ async def create( url="https://api.mydomain.com/webhook", ) """ - _request: typing.Dict[str, typing.Any] = {"triggerType": trigger_type, "url": url} - if filter is not OMIT: - _request["filter"] = filter _response = await self._client_wrapper.httpx_client.request( - "POST", - urllib.parse.urljoin( - f"{self._client_wrapper.get_base_url()}/", f"sites/{jsonable_encoder(site_id)}/webhooks" - ), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - json=jsonable_encoder(_request) - if request_options is None or request_options.get("additional_body_parameters") is None - else { - **jsonable_encoder(_request), - **(jsonable_encoder(remove_none_from_dict(request_options.get("additional_body_parameters", {})))), - }, - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"sites/{jsonable_encoder(site_id)}/webhooks", + method="POST", + json={"triggerType": trigger_type, "url": url, "filter": filter}, + request_options=request_options, + omit=OMIT, ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Webhook, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Webhook, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -426,11 +379,21 @@ async def get(self, webhook_id: str, *, request_options: typing.Optional[Request """ Get a specific Webhook instance - Parameters: - - webhook_id: str. Unique identifier for a Webhook + Parameters + ---------- + webhook_id : str + Unique identifier for a Webhook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Webhook + Request was successful - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -441,36 +404,21 @@ async def get(self, webhook_id: str, *, request_options: typing.Optional[Request ) """ _response = await self._client_wrapper.httpx_client.request( - "GET", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"webhooks/{jsonable_encoder(webhook_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"webhooks/{jsonable_encoder(webhook_id)}", method="GET", request_options=request_options ) - if 200 <= _response.status_code < 300: - return pydantic.parse_obj_as(Webhook, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return pydantic_v1.parse_obj_as(Webhook, _response.json()) # type: ignore + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -480,11 +428,20 @@ async def delete(self, webhook_id: str, *, request_options: typing.Optional[Requ """ Remove a Webhook - Parameters: - - webhook_id: str. Unique identifier for a Webhook + Parameters + ---------- + webhook_id : str + Unique identifier for a Webhook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None - - request_options: typing.Optional[RequestOptions]. Request-specific configuration. - --- + Examples + -------- from webflow.client import AsyncWebflow client = AsyncWebflow( @@ -495,36 +452,21 @@ async def delete(self, webhook_id: str, *, request_options: typing.Optional[Requ ) """ _response = await self._client_wrapper.httpx_client.request( - "DELETE", - urllib.parse.urljoin(f"{self._client_wrapper.get_base_url()}/", f"webhooks/{jsonable_encoder(webhook_id)}"), - params=jsonable_encoder( - request_options.get("additional_query_parameters") if request_options is not None else None - ), - headers=jsonable_encoder( - remove_none_from_dict( - { - **self._client_wrapper.get_headers(), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - timeout=request_options.get("timeout_in_seconds") - if request_options is not None and request_options.get("timeout_in_seconds") is not None - else 60, + f"webhooks/{jsonable_encoder(webhook_id)}", method="DELETE", request_options=request_options ) - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic.parse_obj_as(typing.Any, _response.json())) # type: ignore try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 401: + raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 404: + raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 429: + raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + if _response.status_code == 500: + raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/types/__init__.py b/src/webflow/types/__init__.py index dc0bb64..16b5e7c 100644 --- a/src/webflow/types/__init__.py +++ b/src/webflow/types/__init__.py @@ -14,6 +14,7 @@ from .authorization_authorization import AuthorizationAuthorization from .authorization_authorization_authorized_to import AuthorizationAuthorizationAuthorizedTo from .authorized_user import AuthorizedUser +from .bad_request_error_body import BadRequestErrorBody from .collection import Collection from .collection_item import CollectionItem from .collection_item_field_data import CollectionItemFieldData @@ -21,9 +22,11 @@ from .collection_item_list_pagination import CollectionItemListPagination from .collection_list import CollectionList from .collection_list_array_item import CollectionListArrayItem +from .conflict_error_body import ConflictErrorBody from .custom_code_block import CustomCodeBlock from .custom_code_block_type import CustomCodeBlockType -from .custom_code_response import CustomCodeResponse +from .custom_code_hosted_response import CustomCodeHostedResponse +from .custom_code_inline_response import CustomCodeInlineResponse from .dom import Dom from .domain import Domain from .domains import Domains @@ -33,6 +36,7 @@ from .error_details_item import ErrorDetailsItem from .field import Field from .field_type import FieldType +from .forbidden_error_body import ForbiddenErrorBody from .form import Form from .form_field import FormField from .form_field_value import FormFieldValue @@ -46,6 +50,8 @@ from .inventory_item import InventoryItem from .inventory_item_inventory_type import InventoryItemInventoryType from .list_custom_code_blocks import ListCustomCodeBlocks +from .locale import Locale +from .locales import Locales from .missing_scopes import MissingScopes from .no_domains import NoDomains from .node import Node @@ -71,6 +77,9 @@ from .order_totals_extras_item import OrderTotalsExtrasItem from .order_totals_extras_item_type import OrderTotalsExtrasItemType from .page import Page +from .page_details import PageDetails +from .page_details_open_graph import PageDetailsOpenGraph +from .page_details_seo import PageDetailsSeo from .page_list import PageList from .page_open_graph import PageOpenGraph from .page_seo import PageSeo @@ -93,12 +102,15 @@ from .site_activity_log_item_resource_operation import SiteActivityLogItemResourceOperation from .site_activity_log_item_user import SiteActivityLogItemUser from .site_activity_log_response import SiteActivityLogResponse +from .sites import Sites from .sku import Sku from .sku_field_data import SkuFieldData from .sku_field_data_compare_at_price import SkuFieldDataCompareAtPrice from .sku_field_data_ec_sku_billing_method import SkuFieldDataEcSkuBillingMethod from .sku_field_data_ec_sku_subscription_plan import SkuFieldDataEcSkuSubscriptionPlan from .sku_field_data_ec_sku_subscription_plan_interval import SkuFieldDataEcSkuSubscriptionPlanInterval +from .sku_field_data_ec_sku_subscription_plan_plans_item import SkuFieldDataEcSkuSubscriptionPlanPlansItem +from .sku_field_data_ec_sku_subscription_plan_plans_item_status import SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus from .sku_field_data_price import SkuFieldDataPrice from .sku_property_list import SkuPropertyList from .sku_property_list_enum_item import SkuPropertyListEnumItem @@ -136,6 +148,7 @@ "AuthorizationAuthorization", "AuthorizationAuthorizationAuthorizedTo", "AuthorizedUser", + "BadRequestErrorBody", "Collection", "CollectionItem", "CollectionItemFieldData", @@ -143,9 +156,11 @@ "CollectionItemListPagination", "CollectionList", "CollectionListArrayItem", + "ConflictErrorBody", "CustomCodeBlock", "CustomCodeBlockType", - "CustomCodeResponse", + "CustomCodeHostedResponse", + "CustomCodeInlineResponse", "Dom", "Domain", "Domains", @@ -155,6 +170,7 @@ "ErrorDetailsItem", "Field", "FieldType", + "ForbiddenErrorBody", "Form", "FormField", "FormFieldValue", @@ -168,6 +184,8 @@ "InventoryItem", "InventoryItemInventoryType", "ListCustomCodeBlocks", + "Locale", + "Locales", "MissingScopes", "NoDomains", "Node", @@ -193,6 +211,9 @@ "OrderTotalsExtrasItem", "OrderTotalsExtrasItemType", "Page", + "PageDetails", + "PageDetailsOpenGraph", + "PageDetailsSeo", "PageList", "PageOpenGraph", "PageSeo", @@ -215,12 +236,15 @@ "SiteActivityLogItemResourceOperation", "SiteActivityLogItemUser", "SiteActivityLogResponse", + "Sites", "Sku", "SkuFieldData", "SkuFieldDataCompareAtPrice", "SkuFieldDataEcSkuBillingMethod", "SkuFieldDataEcSkuSubscriptionPlan", "SkuFieldDataEcSkuSubscriptionPlanInterval", + "SkuFieldDataEcSkuSubscriptionPlanPlansItem", + "SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus", "SkuFieldDataPrice", "SkuPropertyList", "SkuPropertyListEnumItem", diff --git a/src/webflow/types/access_group.py b/src/webflow/types/access_group.py index 5e07de0..d0b56f3 100644 --- a/src/webflow/types/access_group.py +++ b/src/webflow/types/access_group.py @@ -4,39 +4,51 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class AccessGroup(pydantic.BaseModel): - id: typing.Optional[str] = pydantic.Field(default=None, description="Unique identifier for the Access Group") - name: typing.Optional[str] = pydantic.Field(default=None, description="Name of the the Access Group") - short_id: typing.Optional[str] = pydantic.Field( - alias="shortId", - default=None, - description="Shortened unique identifier based on name, optimized for its use in the user’s JWT", - ) - slug: typing.Optional[str] = pydantic.Field( - default=None, - description="Shortened unique identifier based on name, optimized for human readability and public API use", - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The date the Access Group was created" - ) + +class AccessGroup(pydantic_v1.BaseModel): + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Unique identifier for the Access Group + """ + + name: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Name of the the Access Group + """ + + short_id: typing.Optional[str] = pydantic_v1.Field(alias="shortId", default=None) + """ + Shortened unique identifier based on name, optimized for its use in the user’s JWT + """ + + slug: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Shortened unique identifier based on name, optimized for human readability and public API use + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The date the Access Group was created + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/access_group_list.py b/src/webflow/types/access_group_list.py index aa36c97..a215c84 100644 --- a/src/webflow/types/access_group_list.py +++ b/src/webflow/types/access_group_list.py @@ -4,39 +4,56 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .access_group import AccessGroup -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class AccessGroupList(pydantic.BaseModel): +class AccessGroupList(pydantic_v1.BaseModel): """ The list access groups results """ - count: typing.Optional[float] = pydantic.Field(default=None, description="Number of access groups returned") - limit: typing.Optional[float] = pydantic.Field(default=None, description="The limit specified in the request") - offset: typing.Optional[float] = pydantic.Field(default=None, description="The offset specified for pagination") - total: typing.Optional[float] = pydantic.Field( - default=None, description="Total number of access groups in the collection" - ) - access_groups: typing.Optional[typing.List[AccessGroup]] = pydantic.Field( - alias="accessGroups", default=None, description="List of Site Access Groups" - ) + count: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Number of access groups returned + """ + + limit: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The limit specified in the request + """ + + offset: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The offset specified for pagination + """ + + total: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Total number of access groups in the collection + """ + + access_groups: typing.Optional[typing.List[AccessGroup]] = pydantic_v1.Field(alias="accessGroups", default=None) + """ + List of Site Access Groups + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/asset.py b/src/webflow/types/asset.py index 0d80162..d76f5ed 100644 --- a/src/webflow/types/asset.py +++ b/src/webflow/types/asset.py @@ -4,36 +4,56 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .asset_variant import AssetVariant -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class Asset(pydantic.BaseModel): - id: typing.Optional[str] = pydantic.Field(default=None, description="Unique identifier for this asset") - content_type: typing.Optional[str] = pydantic.Field( - alias="contentType", default=None, description="File format type" - ) - size: typing.Optional[int] = pydantic.Field(default=None, description="size in bytes") - site_id: typing.Optional[str] = pydantic.Field( - alias="siteId", default=None, description="Unique identifier for the site that hosts this asset" - ) - hosted_url: typing.Optional[str] = pydantic.Field(alias="hostedUrl", default=None, description="Link to the asset") - original_file_name: typing.Optional[str] = pydantic.Field( - alias="originalFileName", default=None, description="Original file name at the time of upload" - ) - display_name: typing.Optional[str] = pydantic.Field( - alias="displayName", default=None, description="Display name of the asset" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="Date the asset metadata was last updated" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="Date the asset metadata was created" - ) + +class Asset(pydantic_v1.BaseModel): + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Unique identifier for this asset + """ + + original_file_name: typing.Optional[str] = pydantic_v1.Field(alias="originalFileName", default=None) + """ + Original file name at the time of upload + """ + + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + Display name of the asset + """ + + content_type: typing.Optional[str] = pydantic_v1.Field(alias="contentType", default=None) + """ + File format type + """ + + size: typing.Optional[int] = pydantic_v1.Field(default=None) + """ + size in bytes + """ + + site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + """ + Unique identifier for the site that hosts this asset + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + Date the asset metadata was created + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + Date the asset metadata was last updated + """ + + hosted_url: typing.Optional[str] = pydantic_v1.Field(alias="hostedUrl", default=None) + """ + Link to the asset + """ + variants: typing.Optional[typing.List[AssetVariant]] = None def json(self, **kwargs: typing.Any) -> str: @@ -41,11 +61,17 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/asset_folder.py b/src/webflow/types/asset_folder.py index 130b755..2406d37 100644 --- a/src/webflow/types/asset_folder.py +++ b/src/webflow/types/asset_folder.py @@ -4,48 +4,65 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class AssetFolder(pydantic.BaseModel): +class AssetFolder(pydantic_v1.BaseModel): """ Asset Folder details """ - display_name: typing.Optional[str] = pydantic.Field( - alias="displayName", default=None, description="User visible name for the Asset Folder" - ) - id: typing.Optional[str] = pydantic.Field(default=None, description="Unique identifier for the Asset Folder") - parent_folder: typing.Optional[str] = pydantic.Field( - alias="parentFolder", default=None, description="Pointer to parent Asset Folder (or null if root)" - ) - assets: typing.Optional[typing.List[str]] = pydantic.Field( - default=None, description="Array of Asset instances in the folder" - ) - site_id: typing.Optional[str] = pydantic.Field( - alias="siteId", default=None, description="The unique id of the site the Asset Folder belongs to" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="Date that the Asset Folder was created on" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="Date that the Asset Folder was last updated on" - ) + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Unique identifier for the Asset Folder + """ + + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + User visible name for the Asset Folder + """ + + parent_folder: typing.Optional[str] = pydantic_v1.Field(alias="parentFolder", default=None) + """ + Pointer to parent Asset Folder (or null if root) + """ + + assets: typing.Optional[typing.List[str]] = pydantic_v1.Field(default=None) + """ + Array of Asset instances in the folder + """ + + site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + """ + The unique id of the site the Asset Folder belongs to + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + Date that the Asset Folder was created on + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + Date that the Asset Folder was last updated on + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/asset_folder_list.py b/src/webflow/types/asset_folder_list.py index 89e533d..0ed82b6 100644 --- a/src/webflow/types/asset_folder_list.py +++ b/src/webflow/types/asset_folder_list.py @@ -4,23 +4,21 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .asset_folder import AssetFolder from .pagination import Pagination -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class AssetFolderList(pydantic.BaseModel): +class AssetFolderList(pydantic_v1.BaseModel): """ The Asset Folders object """ - asset_folders: typing.Optional[typing.List[AssetFolder]] = pydantic.Field( - alias="assetFolders", default=None, description="A list of Asset folders" - ) + asset_folders: typing.Optional[typing.List[AssetFolder]] = pydantic_v1.Field(alias="assetFolders", default=None) + """ + A list of Asset folders + """ + pagination: typing.Optional[Pagination] = None def json(self, **kwargs: typing.Any) -> str: @@ -28,11 +26,17 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/asset_upload.py b/src/webflow/types/asset_upload.py index 299f032..cea12b5 100644 --- a/src/webflow/types/asset_upload.py +++ b/src/webflow/types/asset_upload.py @@ -4,50 +4,65 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .asset_upload_upload_details import AssetUploadUploadDetails -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class AssetUpload(pydantic_v1.BaseModel): + upload_details: typing.Optional[AssetUploadUploadDetails] = pydantic_v1.Field(alias="uploadDetails", default=None) + """ + Metadata for uploading the asset binary + """ -class AssetUpload(pydantic.BaseModel): - upload_details: typing.Optional[AssetUploadUploadDetails] = pydantic.Field( - alias="uploadDetails", default=None, description="Metadata for uploading the asset binary" - ) + content_type: typing.Optional[str] = pydantic_v1.Field(alias="contentType", default=None) id: typing.Optional[str] = None - content_type: typing.Optional[str] = pydantic.Field(alias="contentType", default=None) - parent_folder: typing.Optional[str] = pydantic.Field( - alias="parentFolder", default=None, description="Parent folder for the asset" - ) - hosted_url: typing.Optional[str] = pydantic.Field( - alias="hostedUrl", default=None, description="Represents the link to the asset" - ) - upload_url: typing.Optional[str] = pydantic.Field(alias="uploadUrl", default=None) - asset_url: typing.Optional[str] = pydantic.Field(alias="assetUrl", default=None, description="S3 link to the asset") - original_file_name: typing.Optional[str] = pydantic.Field( - alias="originalFileName", - default=None, - description="Original file name when uploaded. If not specified at time of upload, it may be extracted from the raw file name", - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="Date the asset metadata was last updated" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="Date the asset metadata was created" - ) + parent_folder: typing.Optional[str] = pydantic_v1.Field(alias="parentFolder", default=None) + """ + Parent folder for the asset + """ + + upload_url: typing.Optional[str] = pydantic_v1.Field(alias="uploadUrl", default=None) + asset_url: typing.Optional[str] = pydantic_v1.Field(alias="assetUrl", default=None) + """ + S3 link to the asset + """ + + hosted_url: typing.Optional[str] = pydantic_v1.Field(alias="hostedUrl", default=None) + """ + Represents the link to the asset + """ + + original_file_name: typing.Optional[str] = pydantic_v1.Field(alias="originalFileName", default=None) + """ + Original file name when uploaded. If not specified at time of upload, it may be extracted from the raw file name + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + Date the asset metadata was created + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + Date the asset metadata was last updated + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/asset_upload_upload_details.py b/src/webflow/types/asset_upload_upload_details.py index 244ad84..40735bb 100644 --- a/src/webflow/types/asset_upload_upload_details.py +++ b/src/webflow/types/asset_upload_upload_details.py @@ -4,45 +4,42 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class AssetUploadUploadDetails(pydantic.BaseModel): +class AssetUploadUploadDetails(pydantic_v1.BaseModel): """ Metadata for uploading the asset binary """ acl: typing.Optional[str] = None bucket: typing.Optional[str] = None + x_amz_algorithm: typing.Optional[str] = pydantic_v1.Field(alias="X-Amz-Algorithm", default=None) + x_amz_credential: typing.Optional[str] = pydantic_v1.Field(alias="X-Amz-Credential", default=None) + x_amz_date: typing.Optional[str] = pydantic_v1.Field(alias="X-Amz-Date", default=None) key: typing.Optional[str] = None - policy: typing.Optional[str] = pydantic.Field(alias="Policy", default=None) - x_amz_algorithm: typing.Optional[str] = pydantic.Field(alias="X-Amz-Algorithm", default=None) - x_amz_credential: typing.Optional[str] = pydantic.Field(alias="X-Amz-Credential", default=None) - x_amz_date: typing.Optional[str] = pydantic.Field(alias="X-Amz-Date", default=None) - x_amz_security_token: typing.Optional[str] = pydantic.Field( - alias="X-Amz-Security-Token", - default=None, - description="(optional) Temporary security token obtained when authenticated through AWS STS", - ) - x_amz_signature: typing.Optional[str] = pydantic.Field(alias="X-Amz-Signature", default=None) + policy: typing.Optional[str] = pydantic_v1.Field(alias="Policy", default=None) + x_amz_signature: typing.Optional[str] = pydantic_v1.Field(alias="X-Amz-Signature", default=None) success_action_status: typing.Optional[str] = None - content_type: typing.Optional[str] = pydantic.Field(alias="content-type", default=None) - cache_control: typing.Optional[str] = pydantic.Field(alias="Cache-Control", default=None) + content_type: typing.Optional[str] = pydantic_v1.Field(alias="content-type", default=None) + cache_control: typing.Optional[str] = pydantic_v1.Field(alias="Cache-Control", default=None) def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/asset_variant.py b/src/webflow/types/asset_variant.py index 00af16a..ca4e205 100644 --- a/src/webflow/types/asset_variant.py +++ b/src/webflow/types/asset_variant.py @@ -4,35 +4,66 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class AssetVariant(pydantic_v1.BaseModel): + hosted_url: typing.Optional[str] = pydantic_v1.Field(alias="hostedUrl", default=None) + """ + URL of where the asset variant is hosted + """ -class AssetVariant(pydantic.BaseModel): - hosted_url: typing.Optional[str] = pydantic.Field(alias="hostedUrl", default=None) - original_file_name: typing.Optional[str] = pydantic.Field(alias="originalFileName", default=None) - display_name: typing.Optional[str] = pydantic.Field(alias="displayName", default=None) - format: typing.Optional[str] = None - width: typing.Optional[int] = pydantic.Field(default=None, description="Width in pixels") - height: typing.Optional[int] = pydantic.Field(default=None, description="Height in pixels") - quality: typing.Optional[int] = pydantic.Field( - default=None, description="Value between 0 and 100 representing the image quality" - ) - error: typing.Optional[str] = pydantic.Field(default=None, description="Any associated validation errors") + original_file_name: typing.Optional[str] = pydantic_v1.Field(alias="originalFileName", default=None) + """ + Original file name of the variant + """ + + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + Display name of the variant + """ + + format: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + format of the variant + """ + + width: typing.Optional[int] = pydantic_v1.Field(default=None) + """ + Width in pixels + """ + + height: typing.Optional[int] = pydantic_v1.Field(default=None) + """ + Height in pixels + """ + + quality: typing.Optional[int] = pydantic_v1.Field(default=None) + """ + Value between 0 and 100 representing the image quality + """ + + error: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Any associated validation errors + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/assets.py b/src/webflow/types/assets.py index 3b1ee70..1d4dbfc 100644 --- a/src/webflow/types/assets.py +++ b/src/webflow/types/assets.py @@ -4,15 +4,11 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .asset import Asset -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class Assets(pydantic.BaseModel): +class Assets(pydantic_v1.BaseModel): """ A list of assets """ @@ -24,10 +20,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/authorization.py b/src/webflow/types/authorization.py index c896ac6..ecb2ed7 100644 --- a/src/webflow/types/authorization.py +++ b/src/webflow/types/authorization.py @@ -4,19 +4,17 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .application import Application from .authorization_authorization import AuthorizationAuthorization -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class Authorization(pydantic_v1.BaseModel): + authorization: typing.Optional[AuthorizationAuthorization] = pydantic_v1.Field(default=None) + """ + The Authorization object + """ -class Authorization(pydantic.BaseModel): - authorization: typing.Optional[AuthorizationAuthorization] = pydantic.Field( - default=None, description="The Authorization object" - ) application: typing.Optional[Application] = None def json(self, **kwargs: typing.Any) -> str: @@ -24,10 +22,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/authorization_authorization.py b/src/webflow/types/authorization_authorization.py index cb2780e..9410526 100644 --- a/src/webflow/types/authorization_authorization.py +++ b/src/webflow/types/authorization_authorization.py @@ -4,36 +4,46 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .authorization_authorization_authorized_to import AuthorizationAuthorizationAuthorizedTo -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class AuthorizationAuthorization(pydantic.BaseModel): +class AuthorizationAuthorization(pydantic_v1.BaseModel): """ The Authorization object """ - id: typing.Optional[str] = pydantic.Field(default=None, description="The unique id of the Authorization instance") - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The date the Authorization was created" - ) - last_used: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUsed", default=None, description="The date the Authorization was last used" - ) - grant_type: typing.Optional[str] = pydantic.Field( - alias="grantType", default=None, description="The grant type of the Authorization" - ) - rate_limit: typing.Optional[int] = pydantic.Field( - alias="rateLimit", default=None, description="The default rate limit for the Authorization (requests/min)" - ) - scope: typing.Optional[str] = pydantic.Field( - default=None, description="Comma separted list of OAuth scopes corresponding to the Authorization" - ) - authorized_to: typing.Optional[AuthorizationAuthorizationAuthorizedTo] = pydantic.Field( + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The unique id of the Authorization instance + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The date the Authorization was created + """ + + last_used: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUsed", default=None) + """ + The date the Authorization was last used + """ + + grant_type: typing.Optional[str] = pydantic_v1.Field(alias="grantType", default=None) + """ + The grant type of the Authorization + """ + + rate_limit: typing.Optional[int] = pydantic_v1.Field(alias="rateLimit", default=None) + """ + The default rate limit for the Authorization (requests/min) + """ + + scope: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Comma separted list of OAuth scopes corresponding to the Authorization + """ + + authorized_to: typing.Optional[AuthorizationAuthorizationAuthorizedTo] = pydantic_v1.Field( alias="authorizedTo", default=None ) @@ -42,11 +52,17 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/authorization_authorization_authorized_to.py b/src/webflow/types/authorization_authorization_authorized_to.py index e80f490..cb59ffc 100644 --- a/src/webflow/types/authorization_authorization_authorized_to.py +++ b/src/webflow/types/authorization_authorization_authorized_to.py @@ -4,34 +4,41 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class AuthorizationAuthorizationAuthorizedTo(pydantic_v1.BaseModel): + site_ids: typing.Optional[typing.List[typing.Any]] = pydantic_v1.Field(alias="siteIds", default=None) + """ + Array of Sites this app is authorized to + """ -class AuthorizationAuthorizationAuthorizedTo(pydantic.BaseModel): - site_ids: typing.Optional[typing.List[typing.Any]] = pydantic.Field( - alias="siteIds", default=None, description="Array of Sites this app is authorized to" - ) - workspace_ids: typing.Optional[typing.List[typing.Any]] = pydantic.Field( - alias="workspaceIds", default=None, description="Array of Workspaces this app is authorized to" - ) - user_ids: typing.Optional[typing.List[typing.Any]] = pydantic.Field( - alias="userIds", default=None, description="Array of Users this app is authorized to" - ) + workspace_ids: typing.Optional[typing.List[typing.Any]] = pydantic_v1.Field(alias="workspaceIds", default=None) + """ + Array of Workspaces this app is authorized to + """ + + user_ids: typing.Optional[typing.List[typing.Any]] = pydantic_v1.Field(alias="userIds", default=None) + """ + Array of Users this app is authorized to + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/authorized_user.py b/src/webflow/types/authorized_user.py index 8f754d3..80c4931 100644 --- a/src/webflow/types/authorized_user.py +++ b/src/webflow/types/authorized_user.py @@ -4,31 +4,46 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class AuthorizedUser(pydantic_v1.BaseModel): + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The unique id of the user + """ -class AuthorizedUser(pydantic.BaseModel): - id: typing.Optional[str] = pydantic.Field(default=None, description="The unique id of the user") - email: typing.Optional[str] = pydantic.Field(default=None, description="The user's email address") - first_name: typing.Optional[str] = pydantic.Field( - alias="firstName", default=None, description="The user's first name" - ) - last_name: typing.Optional[str] = pydantic.Field(alias="lastName", default=None, description="The user's last name") + email: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The user's email address + """ + + first_name: typing.Optional[str] = pydantic_v1.Field(alias="firstName", default=None) + """ + The user's first name + """ + + last_name: typing.Optional[str] = pydantic_v1.Field(alias="lastName", default=None) + """ + The user's last name + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/bad_request_error_body.py b/src/webflow/types/bad_request_error_body.py new file mode 100644 index 0000000..6403cc4 --- /dev/null +++ b/src/webflow/types/bad_request_error_body.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from .invalid_domain import InvalidDomain +from .no_domains import NoDomains + +BadRequestErrorBody = typing.Union[InvalidDomain, NoDomains] diff --git a/src/webflow/types/collection.py b/src/webflow/types/collection.py index 6887a61..4be489d 100644 --- a/src/webflow/types/collection.py +++ b/src/webflow/types/collection.py @@ -4,46 +4,66 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from .field import Field -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class Collection(pydantic.BaseModel): +class Collection(pydantic_v1.BaseModel): """ A collection object """ - id: str = pydantic.Field(description="Unique identifier for a Collection") - display_name: typing.Optional[str] = pydantic.Field( - alias="displayName", default=None, description="Name given to the Collection" - ) - singular_name: typing.Optional[str] = pydantic.Field( - alias="singularName", - default=None, - description="The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”)", - ) - slug: typing.Optional[str] = pydantic.Field(default=None, description="Slug of Collection in Site URL structure") - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The date the collection was created" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="The date the collection was last updated" - ) - fields: typing.Dict[str, typing.Any] = pydantic.Field(description="The list of fields in the Collection") + id: str = pydantic_v1.Field() + """ + Unique identifier for a Collection + """ + + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + Name given to the Collection + """ + + singular_name: typing.Optional[str] = pydantic_v1.Field(alias="singularName", default=None) + """ + The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”) + """ + + slug: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Slug of Collection in Site URL structure + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The date the collection was created + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + The date the collection was last updated + """ + + fields: typing.List[Field] = pydantic_v1.Field() + """ + The list of fields in the Collection + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/collection_item.py b/src/webflow/types/collection_item.py index 82a0629..d7e2e1d 100644 --- a/src/webflow/types/collection_item.py +++ b/src/webflow/types/collection_item.py @@ -4,50 +4,68 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .collection_item_field_data import CollectionItemFieldData -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class CollectionItem(pydantic.BaseModel): +class CollectionItem(pydantic_v1.BaseModel): """ The fields that define the schema for a given Item are based on the Collection that Item belongs to. Beyond the user defined fields, there are a handful of additional fields that are automatically created for all items """ - id: str = pydantic.Field(description="Unique identifier for the Item") - cms_locale_id: typing.Optional[str] = pydantic.Field( - alias="cmsLocaleId", default=None, description="Identifier for the locale of the CMS item" - ) - last_published: typing.Optional[str] = pydantic.Field( - alias="lastPublished", default=None, description="The date the item was last published" - ) - last_updated: typing.Optional[str] = pydantic.Field( - alias="lastUpdated", default=None, description="The date the item was last updated" - ) - created_on: typing.Optional[str] = pydantic.Field( - alias="createdOn", default=None, description="The date the item was created" - ) - is_archived: typing.Optional[bool] = pydantic.Field( - alias="isArchived", default=None, description="Boolean determining if the Item is set to archived" - ) - is_draft: typing.Optional[bool] = pydantic.Field( - alias="isDraft", default=None, description="Boolean determining if the Item is set to draft" - ) - field_data: typing.Optional[CollectionItemFieldData] = pydantic.Field(alias="fieldData", default=None) + id: str = pydantic_v1.Field() + """ + Unique identifier for the Item + """ + + cms_locale_id: typing.Optional[str] = pydantic_v1.Field(alias="cmsLocaleId", default=None) + """ + Identifier for the locale of the CMS item + """ + + last_published: typing.Optional[str] = pydantic_v1.Field(alias="lastPublished", default=None) + """ + The date the item was last published + """ + + last_updated: typing.Optional[str] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + The date the item was last updated + """ + + created_on: typing.Optional[str] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The date the item was created + """ + + is_archived: typing.Optional[bool] = pydantic_v1.Field(alias="isArchived", default=None) + """ + Boolean determining if the Item is set to archived + """ + + is_draft: typing.Optional[bool] = pydantic_v1.Field(alias="isDraft", default=None) + """ + Boolean determining if the Item is set to draft + """ + + field_data: typing.Optional[CollectionItemFieldData] = pydantic_v1.Field(alias="fieldData", default=None) def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/collection_item_field_data.py b/src/webflow/types/collection_item_field_data.py index ba2c2fc..19b8588 100644 --- a/src/webflow/types/collection_item_field_data.py +++ b/src/webflow/types/collection_item_field_data.py @@ -4,29 +4,34 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class CollectionItemFieldData(pydantic_v1.BaseModel): + name: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Name of the Item + """ -class CollectionItemFieldData(pydantic.BaseModel): - name: typing.Optional[str] = pydantic.Field(default=None, description="Name of the Item") - slug: typing.Optional[str] = pydantic.Field( - default=None, - description="URL structure of the Item in your site. Note: Updates to an item slug will break all links referencing the old slug.", - ) + slug: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + URL structure of the Item in your site. Note: Updates to an item slug will break all links referencing the old slug. + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/collection_item_list.py b/src/webflow/types/collection_item_list.py index 11f519c..2414299 100644 --- a/src/webflow/types/collection_item_list.py +++ b/src/webflow/types/collection_item_list.py @@ -4,23 +4,21 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .collection_item import CollectionItem from .collection_item_list_pagination import CollectionItemListPagination -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class CollectionItemList(pydantic.BaseModel): +class CollectionItemList(pydantic_v1.BaseModel): """ Results from collection items list """ - items: typing.Optional[typing.List[CollectionItem]] = pydantic.Field( - default=None, description="List of Items within the collection" - ) + items: typing.Optional[typing.List[CollectionItem]] = pydantic_v1.Field(default=None) + """ + List of Items within the collection + """ + pagination: typing.Optional[CollectionItemListPagination] = None def json(self, **kwargs: typing.Any) -> str: @@ -28,10 +26,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/collection_item_list_pagination.py b/src/webflow/types/collection_item_list_pagination.py index ffb4c77..3a7380b 100644 --- a/src/webflow/types/collection_item_list_pagination.py +++ b/src/webflow/types/collection_item_list_pagination.py @@ -4,27 +4,39 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class CollectionItemListPagination(pydantic_v1.BaseModel): + limit: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The limit specified in the request + """ -class CollectionItemListPagination(pydantic.BaseModel): - limit: typing.Optional[float] = pydantic.Field(default=None, description="The limit specified in the request") - offset: typing.Optional[float] = pydantic.Field(default=None, description="The offset specified for pagination") - total: typing.Optional[float] = pydantic.Field(default=None, description="Total number of items in the collection") + offset: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The offset specified for pagination + """ + + total: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Total number of items in the collection + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/collection_list.py b/src/webflow/types/collection_list.py index 683b028..4e5a51c 100644 --- a/src/webflow/types/collection_list.py +++ b/src/webflow/types/collection_list.py @@ -4,28 +4,30 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .collection_list_array_item import CollectionListArrayItem -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class CollectionList(pydantic.BaseModel): - collections: typing.Optional[typing.List[CollectionListArrayItem]] = pydantic.Field( - default=None, description="An array of Collections" - ) +class CollectionList(pydantic_v1.BaseModel): + collections: typing.Optional[typing.List[CollectionListArrayItem]] = pydantic_v1.Field(default=None) + """ + An array of Collections + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/collection_list_array_item.py b/src/webflow/types/collection_list_array_item.py index 2669222..734f947 100644 --- a/src/webflow/types/collection_list_array_item.py +++ b/src/webflow/types/collection_list_array_item.py @@ -4,45 +4,60 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class CollectionListArrayItem(pydantic.BaseModel): +class CollectionListArrayItem(pydantic_v1.BaseModel): """ A collection object """ - id: str = pydantic.Field(description="Unique identifier for a Collection") - display_name: typing.Optional[str] = pydantic.Field( - alias="displayName", default=None, description="Name given to the Collection" - ) - singular_name: typing.Optional[str] = pydantic.Field( - alias="singularName", - default=None, - description="The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”)", - ) - slug: typing.Optional[str] = pydantic.Field(default=None, description="Slug of Collection in Site URL structure") - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The date the collection was created" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="The date the collection was last updated" - ) + id: str = pydantic_v1.Field() + """ + Unique identifier for a Collection + """ + + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + Name given to the Collection + """ + + singular_name: typing.Optional[str] = pydantic_v1.Field(alias="singularName", default=None) + """ + The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”) + """ + + slug: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Slug of Collection in Site URL structure + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The date the collection was created + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + The date the collection was last updated + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/conflict_error_body.py b/src/webflow/types/conflict_error_body.py new file mode 100644 index 0000000..7f34146 --- /dev/null +++ b/src/webflow/types/conflict_error_body.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from .duplicate_user_email import DuplicateUserEmail +from .user_limit_reached import UserLimitReached + +ConflictErrorBody = typing.Union[DuplicateUserEmail, UserLimitReached] diff --git a/src/webflow/types/custom_code_block.py b/src/webflow/types/custom_code_block.py index 20cc019..4252be7 100644 --- a/src/webflow/types/custom_code_block.py +++ b/src/webflow/types/custom_code_block.py @@ -4,47 +4,58 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .custom_code_block_type import CustomCodeBlockType from .scripts import Scripts -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class CustomCodeBlock(pydantic.BaseModel): +class CustomCodeBlock(pydantic_v1.BaseModel): """ A specific instance of Custom Code applied to a Site or Page """ - site_id: typing.Optional[str] = pydantic.Field( - alias="siteId", default=None, description="The Site id where the custom code was applied" - ) - page_id: typing.Optional[str] = pydantic.Field( - alias="pageId", default=None, description="The Page id (if applied at Page-level)" - ) - type: typing.Optional[CustomCodeBlockType] = pydantic.Field( - default=None, description="Whether the Custom Code script is applied at the Site-level or Page-level" - ) + site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + """ + The Site id where the custom code was applied + """ + + page_id: typing.Optional[str] = pydantic_v1.Field(alias="pageId", default=None) + """ + The Page id (if applied at Page-level) + """ + + type: typing.Optional[CustomCodeBlockType] = pydantic_v1.Field(default=None) + """ + Whether the Custom Code script is applied at the Site-level or Page-level + """ + scripts: typing.Optional[Scripts] = None - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The date the Block was created" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="The date the Block was most recently updated" - ) + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The date the Block was created + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + The date the Block was most recently updated + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/custom_code_hosted_response.py b/src/webflow/types/custom_code_hosted_response.py new file mode 100644 index 0000000..61011c3 --- /dev/null +++ b/src/webflow/types/custom_code_hosted_response.py @@ -0,0 +1,73 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 + + +class CustomCodeHostedResponse(pydantic_v1.BaseModel): + """ + Registered custom code for application + """ + + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Human readable id, derived from the user-specified display name + """ + + can_copy: typing.Optional[bool] = pydantic_v1.Field(alias="canCopy", default=None) + """ + Define whether the script can be copied on site duplication and transfer + """ + + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + User-facing name for the script. Must be between 1 and 50 alphanumeric characters + """ + + hosted_location: typing.Optional[str] = pydantic_v1.Field(alias="hostedLocation", default=None) + """ + URI for an externally hosted script location + """ + + integrity_hash: typing.Optional[str] = pydantic_v1.Field(alias="integrityHash", default=None) + """ + Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) + """ + + created_on: typing.Optional[str] = pydantic_v1.Field(alias="createdOn", default=None) + """ + Timestamp when the script version was created + """ + + last_updated: typing.Optional[str] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + Timestamp when the script version was last updated + """ + + version: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + A Semantic Version (SemVer) string, denoting the version of the script + """ + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/custom_code_inline_response.py b/src/webflow/types/custom_code_inline_response.py new file mode 100644 index 0000000..a0301c1 --- /dev/null +++ b/src/webflow/types/custom_code_inline_response.py @@ -0,0 +1,73 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 + + +class CustomCodeInlineResponse(pydantic_v1.BaseModel): + """ + Registered custom code for application + """ + + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Human readable id, derived from the user-specified display name + """ + + can_copy: typing.Optional[bool] = pydantic_v1.Field(alias="canCopy", default=None) + """ + Define whether the script can be copied on site duplication and transfer + """ + + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + User-facing name for the script. Must be between 1 and 50 alphanumeric characters + """ + + hosted_location: typing.Optional[str] = pydantic_v1.Field(alias="hostedLocation", default=None) + """ + URI for an externally hosted script location + """ + + integrity_hash: typing.Optional[str] = pydantic_v1.Field(alias="integrityHash", default=None) + """ + Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) + """ + + created_on: typing.Optional[str] = pydantic_v1.Field(alias="createdOn", default=None) + """ + Timestamp when the script version was created + """ + + last_updated: typing.Optional[str] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + Timestamp when the script version was last updated + """ + + version: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + A Semantic Version (SemVer) string, denoting the version of the script + """ + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/custom_code_response.py b/src/webflow/types/custom_code_response.py deleted file mode 100644 index 2765ca9..0000000 --- a/src/webflow/types/custom_code_response.py +++ /dev/null @@ -1,60 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ..core.datetime_utils import serialize_datetime - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class CustomCodeResponse(pydantic.BaseModel): - """ - Registered custom code for application - """ - - id: typing.Optional[str] = pydantic.Field( - default=None, description="Human readable id, derived from the user-specified display name" - ) - created_on: typing.Optional[str] = pydantic.Field( - alias="createdOn", default=None, description="Timestamp when the script version was created" - ) - last_updated: typing.Optional[str] = pydantic.Field( - alias="lastUpdated", default=None, description="Timestamp when the script version was last updated" - ) - hosted_location: typing.Optional[str] = pydantic.Field( - alias="hostedLocation", default=None, description="URI for an externally hosted script location" - ) - integrity_hash: typing.Optional[str] = pydantic.Field( - alias="integrityHash", - default=None, - description="Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation)", - ) - can_copy: typing.Optional[bool] = pydantic.Field( - alias="canCopy", - default=None, - description="Define whether the script can be copied on site duplication and transfer", - ) - version: typing.Optional[str] = pydantic.Field( - default=None, description="A Semantic Version (SemVer) string, denoting the version of the script" - ) - display_name: typing.Optional[str] = pydantic.Field( - alias="displayName", default=None, description="User-facing name for the script" - ) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/dom.py b/src/webflow/types/dom.py index c6e1d9a..d922f40 100644 --- a/src/webflow/types/dom.py +++ b/src/webflow/types/dom.py @@ -4,21 +4,21 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .node import Node from .pagination import Pagination -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class Dom(pydantic.BaseModel): +class Dom(pydantic_v1.BaseModel): """ The DOM (Document Object Model) schema represents the content structure of a web page. It captures various content nodes, such as text and images, along with their associated attributes. Each node has a unique identifier and can be of different types like text or image. The schema also provides pagination details for scenarios where the content nodes are too many to be fetched in a single request. """ - page_id: typing.Optional[str] = pydantic.Field(alias="pageId", default=None, description="Page ID") + page_id: typing.Optional[str] = pydantic_v1.Field(alias="pageId", default=None) + """ + Page ID + """ + nodes: typing.Optional[typing.List[Node]] = None pagination: typing.Optional[Pagination] = None @@ -27,11 +27,17 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/domain.py b/src/webflow/types/domain.py index 1b69fa5..fdd9a92 100644 --- a/src/webflow/types/domain.py +++ b/src/webflow/types/domain.py @@ -4,26 +4,34 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class Domain(pydantic_v1.BaseModel): + id: str = pydantic_v1.Field() + """ + Unique identifier for the Domain + """ -class Domain(pydantic.BaseModel): - id: str = pydantic.Field(description="Unique identifier for the Domain") - url: typing.Optional[str] = pydantic.Field(default=None, description="The registered Domain name") + url: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The registered Domain name + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/domains.py b/src/webflow/types/domains.py index e9bde11..dcfd0ef 100644 --- a/src/webflow/types/domains.py +++ b/src/webflow/types/domains.py @@ -4,27 +4,29 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .domain import Domain -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class Domains(pydantic.BaseModel): - custom_domains: typing.Optional[typing.List[Domain]] = pydantic.Field(alias="customDomains", default=None) +class Domains(pydantic_v1.BaseModel): + custom_domains: typing.Optional[typing.List[Domain]] = pydantic_v1.Field(alias="customDomains", default=None) def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/duplicate_user_email.py b/src/webflow/types/duplicate_user_email.py index cfc148a..31cf125 100644 --- a/src/webflow/types/duplicate_user_email.py +++ b/src/webflow/types/duplicate_user_email.py @@ -1,37 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt -import typing +from .error import Error -from ..core.datetime_utils import serialize_datetime -from .error_details_item import ErrorDetailsItem - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class DuplicateUserEmail(pydantic.BaseModel): - code: typing.Optional[str] = pydantic.Field(default=None, description="Error code") - message: typing.Optional[str] = pydantic.Field(default=None, description="Error message") - external_reference: typing.Optional[str] = pydantic.Field( - alias="externalReference", default=None, description="Link to more information" - ) - details: typing.Optional[typing.List[ErrorDetailsItem]] = pydantic.Field( - default=None, description="Array of errors" - ) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - json_encoders = {dt.datetime: serialize_datetime} +DuplicateUserEmail = Error diff --git a/src/webflow/types/ecommerce_settings.py b/src/webflow/types/ecommerce_settings.py index 6b6b110..6f58259 100644 --- a/src/webflow/types/ecommerce_settings.py +++ b/src/webflow/types/ecommerce_settings.py @@ -4,38 +4,45 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class EcommerceSettings(pydantic.BaseModel): +class EcommerceSettings(pydantic_v1.BaseModel): """ Ecommerce settings for a Webflow Site """ - site_id: typing.Optional[str] = pydantic.Field( - alias="siteId", default=None, description="The identifier of the Site" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="Date that the Site was created on" - ) - default_currency: typing.Optional[str] = pydantic.Field( - alias="defaultCurrency", default=None, description="The three-letter ISO currency code for the Site" - ) + site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + """ + The identifier of the Site + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + Date that the Site was created on + """ + + default_currency: typing.Optional[str] = pydantic_v1.Field(alias="defaultCurrency", default=None) + """ + The three-letter ISO currency code for the Site + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/error.py b/src/webflow/types/error.py index c8574ab..ead5b4d 100644 --- a/src/webflow/types/error.py +++ b/src/webflow/types/error.py @@ -4,34 +4,47 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .error_details_item import ErrorDetailsItem -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class Error(pydantic_v1.BaseModel): + code: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Error code + """ -class Error(pydantic.BaseModel): - code: typing.Optional[str] = pydantic.Field(default=None, description="Error code") - message: typing.Optional[str] = pydantic.Field(default=None, description="Error message") - external_reference: typing.Optional[str] = pydantic.Field( - alias="externalReference", default=None, description="Link to more information" - ) - details: typing.Optional[typing.List[ErrorDetailsItem]] = pydantic.Field( - default=None, description="Array of errors" - ) + message: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Error message + """ + + external_reference: typing.Optional[str] = pydantic_v1.Field(alias="externalReference", default=None) + """ + Link to more information + """ + + details: typing.Optional[typing.List[ErrorDetailsItem]] = pydantic_v1.Field(default=None) + """ + Array of errors + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/field.py b/src/webflow/types/field.py index a2f8117..d5823cd 100644 --- a/src/webflow/types/field.py +++ b/src/webflow/types/field.py @@ -4,46 +4,66 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .field_type import FieldType -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class Field(pydantic.BaseModel): +class Field(pydantic_v1.BaseModel): """ The details of a field in a collection """ - id: str = pydantic.Field(description="Unique identifier for a Field") - is_required: bool = pydantic.Field( - alias="isRequired", description="define whether a field is required in a collection" - ) - is_editable: typing.Optional[bool] = pydantic.Field( - alias="isEditable", default=None, description="Define whether the field is editable" - ) - type: FieldType = pydantic.Field(description="Choose these appropriate field type for your collection data") - slug: typing.Optional[str] = pydantic.Field( - default=None, - description='Slug of Field in Site URL structure. Slugs should be all lowercase with no spaces. Any spaces will be converted to "-."', - ) - display_name: str = pydantic.Field(alias="displayName", description="The name of a field") - help_text: typing.Optional[str] = pydantic.Field( - alias="helpText", default=None, description="Additional text to help anyone filling out this field" - ) + id: str = pydantic_v1.Field() + """ + Unique identifier for a Field + """ + + is_required: bool = pydantic_v1.Field(alias="isRequired") + """ + define whether a field is required in a collection + """ + + is_editable: typing.Optional[bool] = pydantic_v1.Field(alias="isEditable", default=None) + """ + Define whether the field is editable + """ + + type: FieldType = pydantic_v1.Field() + """ + Choose these appropriate field type for your collection data + """ + + slug: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Slug of Field in Site URL structure. Slugs should be all lowercase with no spaces. Any spaces will be converted to "-." + """ + + display_name: str = pydantic_v1.Field(alias="displayName") + """ + The name of a field + """ + + help_text: typing.Optional[str] = pydantic_v1.Field(alias="helpText", default=None) + """ + Additional text to help anyone filling out this field + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/field_type.py b/src/webflow/types/field_type.py index d40aa66..2b60793 100644 --- a/src/webflow/types/field_type.py +++ b/src/webflow/types/field_type.py @@ -21,7 +21,7 @@ class FieldType(str, enum.Enum): PHONE = "Phone" NUMBER = "Number" DATE_TIME = "DateTime" - BOOLEAN = "Boolean" + SWITCH = "Switch" COLOR = "Color" EXT_FILE_REF = "ExtFileRef" @@ -37,7 +37,7 @@ def visit( phone: typing.Callable[[], T_Result], number: typing.Callable[[], T_Result], date_time: typing.Callable[[], T_Result], - boolean: typing.Callable[[], T_Result], + switch: typing.Callable[[], T_Result], color: typing.Callable[[], T_Result], ext_file_ref: typing.Callable[[], T_Result], ) -> T_Result: @@ -61,8 +61,8 @@ def visit( return number() if self is FieldType.DATE_TIME: return date_time() - if self is FieldType.BOOLEAN: - return boolean() + if self is FieldType.SWITCH: + return switch() if self is FieldType.COLOR: return color() if self is FieldType.EXT_FILE_REF: diff --git a/src/webflow/types/forbidden_error_body.py b/src/webflow/types/forbidden_error_body.py new file mode 100644 index 0000000..7f36dc7 --- /dev/null +++ b/src/webflow/types/forbidden_error_body.py @@ -0,0 +1,35 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 + + +class ForbiddenErrorBody(pydantic_v1.BaseModel): + status: typing.Optional[int] = None + message: typing.Optional[str] = None + public_error_code: typing.Optional[str] = pydantic_v1.Field(alias="publicErrorCode", default=None) + external_reference: typing.Optional[str] = pydantic_v1.Field(alias="externalReference", default=None) + details: typing.Optional[typing.List[str]] = None + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/form.py b/src/webflow/types/form.py index 82a2f69..ae2a5e7 100644 --- a/src/webflow/types/form.py +++ b/src/webflow/types/form.py @@ -4,54 +4,87 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .form_field import FormField from .form_response_settings import FormResponseSettings -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class Form(pydantic.BaseModel): - id: typing.Optional[str] = pydantic.Field(default=None, description="The unique id for the Form") - display_name: typing.Optional[str] = pydantic.Field( - alias="displayName", default=None, description="The Form name displayed on the site" - ) - site_id: typing.Optional[str] = pydantic.Field( - alias="siteId", default=None, description="The unique id of the Site the Form belongs to" - ) - site_domain_id: typing.Optional[str] = pydantic.Field( - alias="siteDomainId", default=None, description="The unique id corresponding to the site's Domain name" - ) - page_id: typing.Optional[str] = pydantic.Field( - alias="pageId", default=None, description="The unique id for the Page on which the Form is placed" - ) - page_name: typing.Optional[str] = pydantic.Field( - alias="pageName", default=None, description="The user-visible name of the Page where the Form is placed" - ) - workspace_id: typing.Optional[str] = pydantic.Field( - alias="workspaceId", default=None, description="The unique id of the Workspace the Site belongs to" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="Date that the Form was created on" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="Date that the Form was last updated on" - ) - fields: typing.Optional[typing.List[FormField]] = None - response_settings: typing.Optional[FormResponseSettings] = pydantic.Field(alias="responseSettings", default=None) + +class Form(pydantic_v1.BaseModel): + """ + A Webflow form + """ + + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + The Form name displayed on the site + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + Date that the Form was created on + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + Date that the Form was last updated on + """ + + fields: typing.Optional[typing.List[FormField]] = pydantic_v1.Field(default=None) + """ + A list of form fields + """ + + response_settings: typing.Optional[FormResponseSettings] = pydantic_v1.Field(alias="responseSettings", default=None) + """ + Settings for form responses + """ + + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The unique id for the Form + """ + + site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + """ + The unique id of the Site the Form belongs to + """ + + site_domain_id: typing.Optional[str] = pydantic_v1.Field(alias="siteDomainId", default=None) + """ + The unique id corresponding to the site's Domain name + """ + + page_id: typing.Optional[str] = pydantic_v1.Field(alias="pageId", default=None) + """ + The unique id for the Page on which the Form is placed + """ + + page_name: typing.Optional[str] = pydantic_v1.Field(alias="pageName", default=None) + """ + The user-visible name of the Page where the Form is placed + """ + + workspace_id: typing.Optional[str] = pydantic_v1.Field(alias="workspaceId", default=None) + """ + The unique id of the Workspace the Site belongs to + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/form_field_value.py b/src/webflow/types/form_field_value.py index dafb390..0a737ca 100644 --- a/src/webflow/types/form_field_value.py +++ b/src/webflow/types/form_field_value.py @@ -4,34 +4,51 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .form_field_value_type import FormFieldValueType -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class FormFieldValue(pydantic_v1.BaseModel): + """ + An object containing field info for a specific fieldID. + """ -class FormFieldValue(pydantic.BaseModel): - display_name: typing.Optional[str] = pydantic.Field( - alias="displayName", default=None, description="The field name displayed on the site" - ) - type: typing.Optional[FormFieldValueType] = pydantic.Field(default=None, description="The field type") - placeholder: typing.Optional[str] = pydantic.Field(default=None, description="The placeholder text for the field") - user_visible: typing.Optional[bool] = pydantic.Field( - alias="userVisible", default=None, description="Whether the field is visible to the user" - ) + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + The field name displayed on the site + """ + + type: typing.Optional[FormFieldValueType] = pydantic_v1.Field(default=None) + """ + The field type + """ + + placeholder: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The placeholder text for the field + """ + + user_visible: typing.Optional[bool] = pydantic_v1.Field(alias="userVisible", default=None) + """ + Whether the field is visible to the user + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/form_list.py b/src/webflow/types/form_list.py index c3f50c5..106dacd 100644 --- a/src/webflow/types/form_list.py +++ b/src/webflow/types/form_list.py @@ -4,16 +4,12 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .form import Form from .pagination import Pagination -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class FormList(pydantic.BaseModel): +class FormList(pydantic_v1.BaseModel): forms: typing.Optional[typing.List[Form]] = None pagination: typing.Optional[Pagination] = None @@ -22,10 +18,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/form_response_settings.py b/src/webflow/types/form_response_settings.py index 06c1264..2a652ab 100644 --- a/src/webflow/types/form_response_settings.py +++ b/src/webflow/types/form_response_settings.py @@ -4,39 +4,50 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class FormResponseSettings(pydantic.BaseModel): - send_email_confirmation: typing.Optional[bool] = pydantic.Field( - alias="sendEmailConfirmation", default=None, description="Whether to send an email confirmation to the user" - ) - redirect_url: typing.Optional[str] = pydantic.Field( - alias="redirectUrl", default=None, description="The url or path to redirect the user to after form submission" - ) - redirect_method: typing.Optional[str] = pydantic.Field( - alias="redirectMethod", - default=None, - description="The HTTP request method to use for the redirectUrl (eg. POST or GET)", - ) - redirect_action: typing.Optional[str] = pydantic.Field( - alias="redirectAction", default=None, description="The action to take after form submission" - ) + +class FormResponseSettings(pydantic_v1.BaseModel): + """ + Settings for form responses + """ + + redirect_url: typing.Optional[str] = pydantic_v1.Field(alias="redirectUrl", default=None) + """ + The url or path to redirect the user to after form submission + """ + + redirect_method: typing.Optional[str] = pydantic_v1.Field(alias="redirectMethod", default=None) + """ + The HTTP request method to use for the redirectUrl (eg. POST or GET) + """ + + redirect_action: typing.Optional[str] = pydantic_v1.Field(alias="redirectAction", default=None) + """ + The action to take after form submission + """ + + send_email_confirmation: typing.Optional[bool] = pydantic_v1.Field(alias="sendEmailConfirmation", default=None) + """ + Whether to send an email confirmation to the user + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/form_submission.py b/src/webflow/types/form_submission.py index c32d501..e55cef3 100644 --- a/src/webflow/types/form_submission.py +++ b/src/webflow/types/form_submission.py @@ -4,41 +4,56 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class FormSubmission(pydantic.BaseModel): - id: typing.Optional[str] = pydantic.Field(default=None, description="The unique id of the Form submission") - display_name: typing.Optional[str] = pydantic.Field( - alias="displayName", default=None, description="The Form name displayed on the site" - ) - site_id: typing.Optional[str] = pydantic.Field( - alias="siteId", default=None, description="The unique id of the Site the Form belongs to" - ) - workspace_id: typing.Optional[str] = pydantic.Field( - alias="workspaceId", default=None, description="The unique id of the Workspace the Site belongs to" - ) - date_submitted: typing.Optional[dt.datetime] = pydantic.Field( - alias="dateSubmitted", default=None, description="Date that the Form was submitted on" - ) - form_response: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field( - alias="formResponse", default=None, description="The data submitted in the Form" - ) + +class FormSubmission(pydantic_v1.BaseModel): + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The unique id of the Form submission + """ + + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + The Form name displayed on the site + """ + + site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + """ + The unique id of the Site the Form belongs to + """ + + workspace_id: typing.Optional[str] = pydantic_v1.Field(alias="workspaceId", default=None) + """ + The unique id of the Workspace the Site belongs to + """ + + date_submitted: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="dateSubmitted", default=None) + """ + Date that the Form was submitted on + """ + + form_response: typing.Optional[typing.Dict[str, typing.Any]] = pydantic_v1.Field(alias="formResponse", default=None) + """ + The data submitted in the Form + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/form_submission_list.py b/src/webflow/types/form_submission_list.py index 78beebd..6222a6a 100644 --- a/src/webflow/types/form_submission_list.py +++ b/src/webflow/types/form_submission_list.py @@ -4,16 +4,12 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .form_submission import FormSubmission from .pagination import Pagination -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class FormSubmissionList(pydantic.BaseModel): +class FormSubmissionList(pydantic_v1.BaseModel): submissions: typing.Optional[typing.List[FormSubmission]] = None pagination: typing.Optional[Pagination] = None @@ -22,10 +18,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/image_node.py b/src/webflow/types/image_node.py index 019874c..89950bf 100644 --- a/src/webflow/types/image_node.py +++ b/src/webflow/types/image_node.py @@ -4,31 +4,33 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class ImageNode(pydantic.BaseModel): +class ImageNode(pydantic_v1.BaseModel): """ Represents an image within the DOM. It contains details about the image, such as its alternative text (alt) for accessibility and an asset identifier for fetching the actual image resource. Additional attributes can be associated with the image for styling or other purposes. """ alt: typing.Optional[str] = None - asset_id: typing.Optional[str] = pydantic.Field(alias="assetId", default=None) + asset_id: typing.Optional[str] = pydantic_v1.Field(alias="assetId", default=None) def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/inventory_item.py b/src/webflow/types/inventory_item.py index d1f66e9..6032815 100644 --- a/src/webflow/types/inventory_item.py +++ b/src/webflow/types/inventory_item.py @@ -4,37 +4,46 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .inventory_item_inventory_type import InventoryItemInventoryType -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class InventoryItem(pydantic.BaseModel): +class InventoryItem(pydantic_v1.BaseModel): """ The availabile inventory for an item """ - id: typing.Optional[str] = pydantic.Field(default=None, description="Unique identifier for a SKU item") - quantity: typing.Optional[float] = pydantic.Field( - default=None, description="Total quantity of items remaining in inventory (if inventoryType is finite)" - ) - inventory_type: typing.Optional[InventoryItemInventoryType] = pydantic.Field( - alias="inventoryType", default=None, description="infinite or finite" - ) + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Unique identifier for a SKU item + """ + + quantity: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Total quantity of items remaining in inventory (if inventoryType is finite) + """ + + inventory_type: typing.Optional[InventoryItemInventoryType] = pydantic_v1.Field(alias="inventoryType", default=None) + """ + infinite or finite + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/list_custom_code_blocks.py b/src/webflow/types/list_custom_code_blocks.py index 20ea276..a67223a 100644 --- a/src/webflow/types/list_custom_code_blocks.py +++ b/src/webflow/types/list_custom_code_blocks.py @@ -4,16 +4,12 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .custom_code_block import CustomCodeBlock from .pagination import Pagination -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class ListCustomCodeBlocks(pydantic.BaseModel): +class ListCustomCodeBlocks(pydantic_v1.BaseModel): """ Custom Code Blocks corresponding to where scripts were applied """ @@ -26,10 +22,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/locale.py b/src/webflow/types/locale.py new file mode 100644 index 0000000..7989af3 --- /dev/null +++ b/src/webflow/types/locale.py @@ -0,0 +1,69 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 + + +class Locale(pydantic_v1.BaseModel): + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The unique identifier for the locale. + """ + + cms_locale_id: typing.Optional[str] = pydantic_v1.Field(alias="cmsLocaleId", default=None) + """ + A CMS-specific identifier for the locale. + """ + + enabled: typing.Optional[bool] = pydantic_v1.Field(default=None) + """ + Indicates if the locale is enabled. + """ + + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + The display name of the locale, typically in English. + """ + + display_image_id: typing.Optional[str] = pydantic_v1.Field(alias="displayImageId", default=None) + """ + An optional ID for an image associated with the locale, nullable. + """ + + redirect: typing.Optional[bool] = pydantic_v1.Field(default=None) + """ + Determines if requests should redirect to the locale's subdirectory. + """ + + subdirectory: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The subdirectory path for the locale, used in URLs. + """ + + tag: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + A tag or code representing the locale, often following a standard format like 'en-US'. + """ + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/locales.py b/src/webflow/types/locales.py new file mode 100644 index 0000000..de37c9b --- /dev/null +++ b/src/webflow/types/locales.py @@ -0,0 +1,38 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from .locale import Locale + + +class Locales(pydantic_v1.BaseModel): + primary: typing.Optional[Locale] = pydantic_v1.Field(default=None) + """ + The primary locale for the site or application. + """ + + secondary: typing.Optional[typing.List[Locale]] = pydantic_v1.Field(default=None) + """ + A list of secondary locales available for the site or application. + """ + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) + + class Config: + frozen = True + smart_union = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/missing_scopes.py b/src/webflow/types/missing_scopes.py index 74e0a7f..a3b4b3e 100644 --- a/src/webflow/types/missing_scopes.py +++ b/src/webflow/types/missing_scopes.py @@ -1,38 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt -import typing +from .error import Error -from ..core.datetime_utils import serialize_datetime -from .error_details_item import ErrorDetailsItem - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class MissingScopes(pydantic.BaseModel): - code: typing.Optional[typing.Literal["missing_scopes"]] = None - type: typing.Optional[str] = None - message: typing.Optional[str] = pydantic.Field(default=None, description="Error message") - external_reference: typing.Optional[str] = pydantic.Field( - alias="externalReference", default=None, description="Link to more information" - ) - details: typing.Optional[typing.List[ErrorDetailsItem]] = pydantic.Field( - default=None, description="Array of errors" - ) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - json_encoders = {dt.datetime: serialize_datetime} +MissingScopes = Error diff --git a/src/webflow/types/node.py b/src/webflow/types/node.py index d15cf06..66370b4 100644 --- a/src/webflow/types/node.py +++ b/src/webflow/types/node.py @@ -4,36 +4,44 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .image_node import ImageNode from .node_type import NodeType from .text_node import TextNode -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class Node(pydantic.BaseModel): +class Node(pydantic_v1.BaseModel): """ A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. """ - id: typing.Optional[str] = pydantic.Field(default=None, description="Node UUID") + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Node UUID + """ + type: typing.Optional[NodeType] = None text: typing.Optional[TextNode] = None image: typing.Optional[ImageNode] = None - attributes: typing.Optional[typing.Dict[str, str]] = None + attributes: typing.Optional[typing.Dict[str, str]] = pydantic_v1.Field(default=None) + """ + The custom attributes of the node + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/not_enterprise_plan_site.py b/src/webflow/types/not_enterprise_plan_site.py index 9c2c607..41410c6 100644 --- a/src/webflow/types/not_enterprise_plan_site.py +++ b/src/webflow/types/not_enterprise_plan_site.py @@ -1,38 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt -import typing +from .error import Error -from ..core.datetime_utils import serialize_datetime -from .error_details_item import ErrorDetailsItem - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class NotEnterprisePlanSite(pydantic.BaseModel): - code: typing.Optional[typing.Literal["missing_scopes"]] = None - type: typing.Optional[str] = None - message: typing.Optional[str] = pydantic.Field(default=None, description="Error message") - external_reference: typing.Optional[str] = pydantic.Field( - alias="externalReference", default=None, description="Link to more information" - ) - details: typing.Optional[typing.List[ErrorDetailsItem]] = pydantic.Field( - default=None, description="Array of errors" - ) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - json_encoders = {dt.datetime: serialize_datetime} +NotEnterprisePlanSite = Error diff --git a/src/webflow/types/oauth_scope.py b/src/webflow/types/oauth_scope.py index 2d49caa..59ad0fd 100644 --- a/src/webflow/types/oauth_scope.py +++ b/src/webflow/types/oauth_scope.py @@ -97,6 +97,16 @@ class OauthScope(str, enum.Enum): modify users on the site """ + WORKSPACE_READ = "workspace:read" + """ + read workspace resource data + """ + + WORKSPACE_WRITE = "workspace:write" + """ + write workspace resource data + """ + def visit( self, authorized_user_read: typing.Callable[[], T_Result], @@ -117,6 +127,8 @@ def visit( users_read: typing.Callable[[], T_Result], site_activity_read: typing.Callable[[], T_Result], users_write: typing.Callable[[], T_Result], + workspace_read: typing.Callable[[], T_Result], + workspace_write: typing.Callable[[], T_Result], ) -> T_Result: if self is OauthScope.AUTHORIZED_USER_READ: return authorized_user_read() @@ -154,3 +166,7 @@ def visit( return site_activity_read() if self is OauthScope.USERS_WRITE: return users_write() + if self is OauthScope.WORKSPACE_READ: + return workspace_read() + if self is OauthScope.WORKSPACE_WRITE: + return workspace_write() diff --git a/src/webflow/types/order.py b/src/webflow/types/order.py index 9f7cdd6..f4be90d 100644 --- a/src/webflow/types/order.py +++ b/src/webflow/types/order.py @@ -4,6 +4,7 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .order_address import OrderAddress from .order_customer_info import OrderCustomerInfo from .order_dispute_last_status import OrderDisputeLastStatus @@ -17,139 +18,177 @@ from .stripe_card import StripeCard from .stripe_details import StripeDetails -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class Order(pydantic_v1.BaseModel): + order_id: typing.Optional[str] = pydantic_v1.Field(alias="orderId", default=None) + """ + The order id. Will usually be 6 hex characters, but can also be 9 hex characters if the site has a very large number of Orders. Randomly assigned. + """ -class Order(pydantic.BaseModel): - order_id: typing.Optional[str] = pydantic.Field( - alias="orderId", - default=None, - description="The order id. Will usually be 6 hex characters, but can also be 9 hex characters if the site has a very large number of Orders. Randomly assigned.", - ) - status: typing.Optional[OrderStatus] = pydantic.Field(default=None, description="The status of the Order") - comment: typing.Optional[str] = pydantic.Field( - default=None, description="A comment string for this Order editable by API user (not used by Webflow)." - ) - order_comment: typing.Optional[str] = pydantic.Field( - alias="orderComment", default=None, description="A comment that the customer left when making their Order" - ) - accepted_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="acceptedOn", default=None, description="The ISO8601 timestamp that an Order was placed." - ) - fulfilled_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="fulfilledOn", - default=None, - description="If an Order was marked as 'fulfilled', then this is the ISO8601 timestamp when that happened.", - ) - refunded_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="refundedOn", - default=None, - description="If an Order was refunded, this is the ISO8601 of when that happened.", - ) - disputed_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="disputedOn", - default=None, - description="If an Order was disputed by the customer, then this key will be set with the ISO8601 timestamp that Stripe notifies Webflow. Null if not disputed.", - ) - dispute_updated_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="disputeUpdatedOn", - default=None, - description="If an Order was disputed by the customer, then this key will be set with the ISO8601 timestamp of the last time that we got an update. Null if not disputed.", - ) - dispute_last_status: typing.Optional[OrderDisputeLastStatus] = pydantic.Field( - alias="disputeLastStatus", - default=None, - description="If an order was disputed by the customer, then this key will be set with the [dispute's status](https://stripe.com/docs/api#dispute_object-status).", - ) - customer_paid: typing.Optional[OrderPrice] = pydantic.Field( - alias="customerPaid", default=None, description="The total paid by the customer" - ) - net_amount: typing.Optional[OrderPrice] = pydantic.Field( - alias="netAmount", default=None, description="The net amount after application fees" - ) - application_fee: typing.Optional[OrderPrice] = pydantic.Field( - alias="applicationFee", default=None, description="The application fee assessed by the platform" - ) - all_addresses: typing.Optional[typing.List[OrderAddress]] = pydantic.Field( - alias="allAddresses", - default=None, - description="All addresses provided by the customer during the ordering flow.", - ) - shipping_address: typing.Optional[OrderAddress] = pydantic.Field( - alias="shippingAddress", default=None, description="The shipping address" - ) - billing_address: typing.Optional[OrderAddress] = pydantic.Field( - alias="billingAddress", default=None, description="The billing address" - ) - shipping_provider: typing.Optional[str] = pydantic.Field( - alias="shippingProvider", - default=None, - description="A string editable by the API user to note the shipping provider used (not used by Webflow).", - ) - shipping_tracking: typing.Optional[str] = pydantic.Field( - alias="shippingTracking", - default=None, - description="A string editable by the API user to note the shipping tracking number for the order (not used by Webflow).", - ) - shipping_tracking_url: typing.Optional[str] = pydantic.Field(alias="shippingTrackingURL", default=None) - customer_info: typing.Optional[OrderCustomerInfo] = pydantic.Field( - alias="customerInfo", default=None, description="An object with the keys `fullName` and `email`." - ) - purchased_items: typing.Optional[typing.List[OrderPurchasedItem]] = pydantic.Field( - alias="purchasedItems", default=None, description="An array of all things that the Customer purchased." - ) - purchased_items_count: typing.Optional[float] = pydantic.Field( - alias="purchasedItemsCount", default=None, description="The sum of all 'count' fields in 'purchasedItems'." + status: typing.Optional[OrderStatus] = pydantic_v1.Field(default=None) + """ + The status of the Order + """ + + comment: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + A comment string for this Order, which is editable by API user (not used by Webflow). + """ + + order_comment: typing.Optional[str] = pydantic_v1.Field(alias="orderComment", default=None) + """ + A comment that the customer left when making their Order + """ + + accepted_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="acceptedOn", default=None) + """ + The ISO8601 timestamp that an Order was placed. + """ + + fulfilled_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="fulfilledOn", default=None) + """ + When an Order is marked as 'fulfilled', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. + """ + + refunded_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="refundedOn", default=None) + """ + When an Order is marked as 'refunded', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. + """ + + disputed_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="disputedOn", default=None) + """ + When an Order is marked as 'disputed', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. + """ + + dispute_updated_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="disputeUpdatedOn", default=None) + """ + If an Order has been disputed by the customer, this key will be set to the ISO8601 timestamp of the last update received. If the Order is not disputed, the key will be null. + """ + + dispute_last_status: typing.Optional[OrderDisputeLastStatus] = pydantic_v1.Field( + alias="disputeLastStatus", default=None ) - stripe_details: typing.Optional[StripeDetails] = pydantic.Field(alias="stripeDetails", default=None) - stripe_card: typing.Optional[StripeCard] = pydantic.Field(alias="stripeCard", default=None) - paypal_details: typing.Optional[PaypalDetails] = pydantic.Field(alias="paypalDetails", default=None) - custom_data: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = pydantic.Field( - alias="customData", - default=None, - description="An array of additional inputs for custom order data gathering. Each object in the array represents an input with a name, and a textInput, textArea, or checkbox value.", + """ + If an order was disputed by the customer, then this key will be set with the [dispute's status](https://stripe.com/docs/api#dispute_object-status). + """ + + customer_paid: typing.Optional[OrderPrice] = pydantic_v1.Field(alias="customerPaid", default=None) + """ + The total paid by the customer + """ + + net_amount: typing.Optional[OrderPrice] = pydantic_v1.Field(alias="netAmount", default=None) + """ + The net amount after application fees + """ + + application_fee: typing.Optional[OrderPrice] = pydantic_v1.Field(alias="applicationFee", default=None) + """ + The application fee assessed by the platform + """ + + all_addresses: typing.Optional[typing.List[OrderAddress]] = pydantic_v1.Field(alias="allAddresses", default=None) + """ + All addresses provided by the customer during the ordering flow. + """ + + shipping_address: typing.Optional[OrderAddress] = pydantic_v1.Field(alias="shippingAddress", default=None) + """ + The shipping address + """ + + billing_address: typing.Optional[OrderAddress] = pydantic_v1.Field(alias="billingAddress", default=None) + """ + The billing address + """ + + shipping_provider: typing.Optional[str] = pydantic_v1.Field(alias="shippingProvider", default=None) + """ + A string editable by the API user to note the shipping provider used (not used by Webflow). + """ + + shipping_tracking: typing.Optional[str] = pydantic_v1.Field(alias="shippingTracking", default=None) + """ + A string editable by the API user to note the shipping tracking number for the order (not used by Webflow). + """ + + shipping_tracking_url: typing.Optional[str] = pydantic_v1.Field(alias="shippingTrackingURL", default=None) + customer_info: typing.Optional[OrderCustomerInfo] = pydantic_v1.Field(alias="customerInfo", default=None) + """ + An object with the keys `fullName` and `email`. + """ + + purchased_items: typing.Optional[typing.List[OrderPurchasedItem]] = pydantic_v1.Field( + alias="purchasedItems", default=None ) + """ + An array of all things that the Customer purchased. + """ + + purchased_items_count: typing.Optional[float] = pydantic_v1.Field(alias="purchasedItemsCount", default=None) + """ + The sum of all 'count' fields in 'purchasedItems'. + """ + + stripe_details: typing.Optional[StripeDetails] = pydantic_v1.Field(alias="stripeDetails", default=None) + stripe_card: typing.Optional[StripeCard] = pydantic_v1.Field(alias="stripeCard", default=None) + paypal_details: typing.Optional[PaypalDetails] = pydantic_v1.Field(alias="paypalDetails", default=None) + custom_data: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = pydantic_v1.Field( + alias="customData", default=None + ) + """ + An array of additional inputs for custom order data gathering. Each object in the array represents an input with a name, and a textInput, textArea, or checkbox value. + """ + metadata: typing.Optional[OrderMetadata] = None - is_customer_deleted: typing.Optional[bool] = pydantic.Field( - alias="isCustomerDeleted", - default=None, - description="A boolean indicating whether the customer has been deleted from the site.", - ) - is_shipping_required: typing.Optional[bool] = pydantic.Field( - alias="isShippingRequired", - default=None, - description="A boolean indicating whether the order contains one or more purchased items that require shipping.", - ) - has_downloads: typing.Optional[bool] = pydantic.Field( - alias="hasDownloads", - default=None, - description="A boolean indicating whether the order contains one or more purchased items that are downloadable.", - ) - payment_processor: typing.Optional[str] = pydantic.Field( - alias="paymentProcessor", - default=None, - description="A string indicating the payment processor used for this order.", - ) - totals: typing.Optional[OrderTotals] = pydantic.Field( - default=None, description="An object describing various pricing totals" - ) - download_files: typing.Optional[typing.List[OrderDownloadFilesItem]] = pydantic.Field( - alias="downloadFiles", default=None, description="An array of downloadable file objects." + is_customer_deleted: typing.Optional[bool] = pydantic_v1.Field(alias="isCustomerDeleted", default=None) + """ + A boolean indicating whether the customer has been deleted from the site. + """ + + is_shipping_required: typing.Optional[bool] = pydantic_v1.Field(alias="isShippingRequired", default=None) + """ + A boolean indicating whether the order contains one or more purchased items that require shipping. + """ + + has_downloads: typing.Optional[bool] = pydantic_v1.Field(alias="hasDownloads", default=None) + """ + A boolean indicating whether the order contains one or more purchased items that are downloadable. + """ + + payment_processor: typing.Optional[str] = pydantic_v1.Field(alias="paymentProcessor", default=None) + """ + A string indicating the payment processor used for this order. + """ + + totals: typing.Optional[OrderTotals] = pydantic_v1.Field(default=None) + """ + An object describing various pricing totals + """ + + download_files: typing.Optional[typing.List[OrderDownloadFilesItem]] = pydantic_v1.Field( + alias="downloadFiles", default=None ) + """ + An array of downloadable file objects. + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_address.py b/src/webflow/types/order_address.py index a22a3de..5e7ec60 100644 --- a/src/webflow/types/order_address.py +++ b/src/webflow/types/order_address.py @@ -4,50 +4,77 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .order_address_japan_type import OrderAddressJapanType from .order_address_type import OrderAddressType -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class OrderAddress(pydantic.BaseModel): +class OrderAddress(pydantic_v1.BaseModel): """ A customer address """ - type: typing.Optional[OrderAddressType] = pydantic.Field( - default=None, description="The type of the order address (billing or shipping)" - ) - japan_type: typing.Optional[OrderAddressJapanType] = pydantic.Field( - alias="japanType", default=None, description="Japan-only address format" - ) - addressee: typing.Optional[str] = pydantic.Field(default=None, description="Display name on the address") - line_1: typing.Optional[str] = pydantic.Field( - alias="line1", default=None, description="The first line of the address" - ) - line_2: typing.Optional[str] = pydantic.Field( - alias="line2", default=None, description="The second line of the address" - ) - city: typing.Optional[str] = pydantic.Field(default=None, description="The city of the address.") - state: typing.Optional[str] = pydantic.Field(default=None, description="The state or province of the address") - country: typing.Optional[str] = pydantic.Field(default=None, description="The country of the address") - postal_code: typing.Optional[str] = pydantic.Field( - alias="postalCode", default=None, description="The postal code of the address" - ) + type: typing.Optional[OrderAddressType] = pydantic_v1.Field(default=None) + """ + The type of the order address (billing or shipping) + """ + + japan_type: typing.Optional[OrderAddressJapanType] = pydantic_v1.Field(alias="japanType", default=None) + """ + Represents a Japan-only address format. This field will only appear on orders placed from Japan. + """ + + addressee: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Display name on the address + """ + + line_1: typing.Optional[str] = pydantic_v1.Field(alias="line1", default=None) + """ + The first line of the address + """ + + line_2: typing.Optional[str] = pydantic_v1.Field(alias="line2", default=None) + """ + The second line of the address + """ + + city: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The city of the address. + """ + + state: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The state or province of the address + """ + + country: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The country of the address + """ + + postal_code: typing.Optional[str] = pydantic_v1.Field(alias="postalCode", default=None) + """ + The postal code of the address + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_address_japan_type.py b/src/webflow/types/order_address_japan_type.py index 053942b..648e1a4 100644 --- a/src/webflow/types/order_address_japan_type.py +++ b/src/webflow/types/order_address_japan_type.py @@ -8,7 +8,7 @@ class OrderAddressJapanType(str, enum.Enum): """ - Japan-only address format + Represents a Japan-only address format. This field will only appear on orders placed from Japan. """ KANA = "kana" diff --git a/src/webflow/types/order_customer_info.py b/src/webflow/types/order_customer_info.py index e0486d2..1527e4a 100644 --- a/src/webflow/types/order_customer_info.py +++ b/src/webflow/types/order_customer_info.py @@ -4,33 +4,40 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class OrderCustomerInfo(pydantic.BaseModel): +class OrderCustomerInfo(pydantic_v1.BaseModel): """ An object with the keys `fullName` and `email`. """ - full_name: typing.Optional[str] = pydantic.Field( - alias="fullName", default=None, description="The full name of the Customer" - ) - email: typing.Optional[str] = pydantic.Field(default=None, description="The Customer's email address") + full_name: typing.Optional[str] = pydantic_v1.Field(alias="fullName", default=None) + """ + The full name of the Customer + """ + + email: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The Customer's email address + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_download_files_item.py b/src/webflow/types/order_download_files_item.py index 15a3210..e910b46 100644 --- a/src/webflow/types/order_download_files_item.py +++ b/src/webflow/types/order_download_files_item.py @@ -4,33 +4,39 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class OrderDownloadFilesItem(pydantic_v1.BaseModel): + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The unique identifier for the downloadable file + """ -class OrderDownloadFilesItem(pydantic.BaseModel): - id: typing.Optional[str] = pydantic.Field( - default=None, description="The unique identifier for the downloadable file" - ) - name: typing.Optional[str] = pydantic.Field( - default=None, description="The user-facing name for the downloadable file" - ) - url: typing.Optional[str] = pydantic.Field( - default=None, description="The hosted location for the downloadable file" - ) + name: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The user-facing name for the downloadable file + """ + + url: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The hosted location for the downloadable file + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_list.py b/src/webflow/types/order_list.py index 2ad1b84..fe867c8 100644 --- a/src/webflow/types/order_list.py +++ b/src/webflow/types/order_list.py @@ -4,21 +4,21 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .order import Order from .pagination import Pagination -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class OrderList(pydantic.BaseModel): +class OrderList(pydantic_v1.BaseModel): """ Results from order list """ - items: typing.Optional[typing.List[Order]] = pydantic.Field(default=None, description="List of orders") + orders: typing.Optional[typing.List[Order]] = pydantic_v1.Field(default=None) + """ + List of orders + """ + pagination: typing.Optional[Pagination] = None def json(self, **kwargs: typing.Any) -> str: @@ -26,10 +26,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_metadata.py b/src/webflow/types/order_metadata.py index d37fc38..b1ebcd8 100644 --- a/src/webflow/types/order_metadata.py +++ b/src/webflow/types/order_metadata.py @@ -4,26 +4,28 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class OrderMetadata(pydantic.BaseModel): - is_buy_now: typing.Optional[bool] = pydantic.Field(alias="isBuyNow", default=None) +class OrderMetadata(pydantic_v1.BaseModel): + is_buy_now: typing.Optional[bool] = pydantic_v1.Field(alias="isBuyNow", default=None) def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_price.py b/src/webflow/types/order_price.py index 36012d1..28be474 100644 --- a/src/webflow/types/order_price.py +++ b/src/webflow/types/order_price.py @@ -4,31 +4,39 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class OrderPrice(pydantic_v1.BaseModel): + unit: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The three-letter ISO currency code + """ -class OrderPrice(pydantic.BaseModel): - unit: typing.Optional[str] = pydantic.Field(default=None, description="The three-letter ISO currency code") - value: typing.Optional[str] = pydantic.Field( - default=None, description="The numeric value in the base unit of the currency" - ) - string: typing.Optional[str] = pydantic.Field( - default=None, description="The user-facing string representation of the amount" - ) + value: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The numeric value in the base unit of the currency + """ + + string: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The user-facing string representation of the amount + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_purchased_item.py b/src/webflow/types/order_purchased_item.py index f2250aa..a35a732 100644 --- a/src/webflow/types/order_purchased_item.py +++ b/src/webflow/types/order_purchased_item.py @@ -4,69 +4,105 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .order_price import OrderPrice from .order_purchased_item_variant_image import OrderPurchasedItemVariantImage -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class OrderPurchasedItem(pydantic.BaseModel): +class OrderPurchasedItem(pydantic_v1.BaseModel): """ An Item that was purchased """ - count: typing.Optional[float] = pydantic.Field(default=None, description="Number of Item purchased.") - row_total: typing.Optional[OrderPrice] = pydantic.Field( - alias="rowTotal", default=None, description="The total for the row" - ) - product_id: typing.Optional[str] = pydantic.Field( - alias="productId", default=None, description="The unique identifier for the Product" - ) - product_name: typing.Optional[str] = pydantic.Field( - alias="productName", default=None, description="User-facing name of the Product" - ) - product_slug: typing.Optional[str] = pydantic.Field( - alias="productSlug", default=None, description="Slug for the Product" - ) - variant_id: typing.Optional[str] = pydantic.Field( - alias="variantId", default=None, description="Identifier for the Product Variant (SKU)" - ) - variant_name: typing.Optional[str] = pydantic.Field( - alias="variantName", default=None, description="User-facing name of the Product Variant (SKU)" - ) - variant_slug: typing.Optional[str] = pydantic.Field( - alias="variantSlug", default=None, description="Slug for the Product Variant (SKU)" - ) - variant_image: typing.Optional[OrderPurchasedItemVariantImage] = pydantic.Field(alias="variantImage", default=None) - variant_price: typing.Optional[OrderPrice] = pydantic.Field( - alias="variantPrice", default=None, description="The price corresponding to the variant" - ) - weight: typing.Optional[float] = pydantic.Field( - default=None, description="The physical weight of the variant if provided, or null" - ) - width: typing.Optional[float] = pydantic.Field( - default=None, description="The physical width of the variant if provided, or null" - ) - height: typing.Optional[float] = pydantic.Field( - default=None, description="The physical height of the variant if provided, or null" - ) - length: typing.Optional[float] = pydantic.Field( - default=None, description="The physical length of the variant if provided, or null" + count: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Number of Item purchased. + """ + + row_total: typing.Optional[OrderPrice] = pydantic_v1.Field(alias="rowTotal", default=None) + """ + The total for the row + """ + + product_id: typing.Optional[str] = pydantic_v1.Field(alias="productId", default=None) + """ + The unique identifier for the Product + """ + + product_name: typing.Optional[str] = pydantic_v1.Field(alias="productName", default=None) + """ + User-facing name of the Product + """ + + product_slug: typing.Optional[str] = pydantic_v1.Field(alias="productSlug", default=None) + """ + Slug for the Product + """ + + variant_id: typing.Optional[str] = pydantic_v1.Field(alias="variantId", default=None) + """ + Identifier for the Product Variant (SKU) + """ + + variant_name: typing.Optional[str] = pydantic_v1.Field(alias="variantName", default=None) + """ + User-facing name of the Product Variant (SKU) + """ + + variant_slug: typing.Optional[str] = pydantic_v1.Field(alias="variantSlug", default=None) + """ + Slug for the Product Variant (SKU) + """ + + variant_sku: typing.Optional[str] = pydantic_v1.Field(alias="variantSKU", default=None) + """ + The user-defined custom SKU of the Product Variant (SKU) + """ + + variant_image: typing.Optional[OrderPurchasedItemVariantImage] = pydantic_v1.Field( + alias="variantImage", default=None ) + variant_price: typing.Optional[OrderPrice] = pydantic_v1.Field(alias="variantPrice", default=None) + """ + The price corresponding to the variant + """ + + weight: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The physical weight of the variant if provided, or null + """ + + width: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The physical width of the variant if provided, or null + """ + + height: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The physical height of the variant if provided, or null + """ + + length: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The physical length of the variant if provided, or null + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_purchased_item_variant_image.py b/src/webflow/types/order_purchased_item_variant_image.py index 0b31d99..837ab2d 100644 --- a/src/webflow/types/order_purchased_item_variant_image.py +++ b/src/webflow/types/order_purchased_item_variant_image.py @@ -4,16 +4,16 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .order_purchased_item_variant_image_file import OrderPurchasedItemVariantImageFile -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class OrderPurchasedItemVariantImage(pydantic_v1.BaseModel): + url: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The hosted location for the Variant's image + """ -class OrderPurchasedItemVariantImage(pydantic.BaseModel): - url: typing.Optional[str] = pydantic.Field(default=None, description="The hosted location for the Variant's image") file: typing.Optional[OrderPurchasedItemVariantImageFile] = None def json(self, **kwargs: typing.Any) -> str: @@ -21,10 +21,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_purchased_item_variant_image_file.py b/src/webflow/types/order_purchased_item_variant_image_file.py index 9d73a2d..b6c273f 100644 --- a/src/webflow/types/order_purchased_item_variant_image_file.py +++ b/src/webflow/types/order_purchased_item_variant_image_file.py @@ -4,41 +4,64 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .order_purchased_item_variant_image_file_variants_item import OrderPurchasedItemVariantImageFileVariantsItem -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class OrderPurchasedItemVariantImageFile(pydantic_v1.BaseModel): + size: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The image size in bytes + """ -class OrderPurchasedItemVariantImageFile(pydantic.BaseModel): - size: typing.Optional[float] = pydantic.Field(default=None, description="The image size in bytes") - original_file_name: typing.Optional[str] = pydantic.Field( - alias="originalFileName", default=None, description="the original name of the image" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The creation timestamp of the image" - ) - content_type: typing.Optional[str] = pydantic.Field( - alias="contentType", default=None, description="The MIME type of the image" - ) - width: typing.Optional[int] = pydantic.Field(default=None, description="The image width in pixels") - height: typing.Optional[int] = pydantic.Field(default=None, description="The image height in pixels") - variants: typing.Optional[typing.List[OrderPurchasedItemVariantImageFileVariantsItem]] = pydantic.Field( - default=None, description="Variants of the supplied image" + original_file_name: typing.Optional[str] = pydantic_v1.Field(alias="originalFileName", default=None) + """ + the original name of the image + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The creation timestamp of the image + """ + + content_type: typing.Optional[str] = pydantic_v1.Field(alias="contentType", default=None) + """ + The MIME type of the image + """ + + width: typing.Optional[int] = pydantic_v1.Field(default=None) + """ + The image width in pixels + """ + + height: typing.Optional[int] = pydantic_v1.Field(default=None) + """ + The image height in pixels + """ + + variants: typing.Optional[typing.List[OrderPurchasedItemVariantImageFileVariantsItem]] = pydantic_v1.Field( + default=None ) + """ + Variants of the supplied image + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py b/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py index fc37a0d..687898b 100644 --- a/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py +++ b/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py @@ -4,30 +4,47 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class OrderPurchasedItemVariantImageFileVariantsItem(pydantic_v1.BaseModel): + url: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The hosted location for the Variant's image + """ -class OrderPurchasedItemVariantImageFileVariantsItem(pydantic.BaseModel): - url: typing.Optional[str] = pydantic.Field(default=None, description="The hosted location for the Variant's image") - original_file_name: typing.Optional[str] = pydantic.Field(alias="originalFileName", default=None) - size: typing.Optional[float] = pydantic.Field(default=None, description="The image size in bytes") - width: typing.Optional[int] = pydantic.Field(default=None, description="The image width in pixels") - height: typing.Optional[int] = pydantic.Field(default=None, description="The image height in pixels") + original_file_name: typing.Optional[str] = pydantic_v1.Field(alias="originalFileName", default=None) + size: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The image size in bytes + """ + + width: typing.Optional[int] = pydantic_v1.Field(default=None) + """ + The image width in pixels + """ + + height: typing.Optional[int] = pydantic_v1.Field(default=None) + """ + The image height in pixels + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_totals.py b/src/webflow/types/order_totals.py index ef88075..bed4a4f 100644 --- a/src/webflow/types/order_totals.py +++ b/src/webflow/types/order_totals.py @@ -4,35 +4,45 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .order_price import OrderPrice from .order_totals_extras_item import OrderTotalsExtrasItem -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class OrderTotals(pydantic.BaseModel): +class OrderTotals(pydantic_v1.BaseModel): """ An object describing various pricing totals """ - subtotal: typing.Optional[OrderPrice] = pydantic.Field(default=None, description="The subtotal price") - extras: typing.Optional[typing.List[OrderTotalsExtrasItem]] = pydantic.Field( - default=None, description="An array of extra items, includes discounts, shipping, and taxes." - ) - total: typing.Optional[OrderPrice] = pydantic.Field(default=None, description="The total price") + subtotal: typing.Optional[OrderPrice] = pydantic_v1.Field(default=None) + """ + The subtotal price + """ + + extras: typing.Optional[typing.List[OrderTotalsExtrasItem]] = pydantic_v1.Field(default=None) + """ + An array of extra items, includes discounts, shipping, and taxes. + """ + + total: typing.Optional[OrderPrice] = pydantic_v1.Field(default=None) + """ + The total price + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/order_totals_extras_item.py b/src/webflow/types/order_totals_extras_item.py index e2a70e0..7c0b399 100644 --- a/src/webflow/types/order_totals_extras_item.py +++ b/src/webflow/types/order_totals_extras_item.py @@ -4,40 +4,50 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .order_price import OrderPrice from .order_totals_extras_item_type import OrderTotalsExtrasItemType -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class OrderTotalsExtrasItem(pydantic.BaseModel): +class OrderTotalsExtrasItem(pydantic_v1.BaseModel): """ Extra order items, includes discounts, shipping, and taxes. """ - type: typing.Optional[OrderTotalsExtrasItemType] = pydantic.Field( - default=None, description="The type of extra item this is." - ) - name: typing.Optional[str] = pydantic.Field( - default=None, description="A human-readable (but English) name for this extra charge." - ) - description: typing.Optional[str] = pydantic.Field( - default=None, description="A human-readable (but English) description of this extra charge." - ) - price: typing.Optional[OrderPrice] = pydantic.Field(default=None, description="The price for the item") + type: typing.Optional[OrderTotalsExtrasItemType] = pydantic_v1.Field(default=None) + """ + The type of extra item this is. + """ + + name: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + A human-readable (but English) name for this extra charge. + """ + + description: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + A human-readable (but English) description of this extra charge. + """ + + price: typing.Optional[OrderPrice] = pydantic_v1.Field(default=None) + """ + The price for the item + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/page.py b/src/webflow/types/page.py index f67e4b2..4995ea4 100644 --- a/src/webflow/types/page.py +++ b/src/webflow/types/page.py @@ -4,67 +4,102 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .page_open_graph import PageOpenGraph from .page_seo import PageSeo -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class Page(pydantic.BaseModel): +class Page(pydantic_v1.BaseModel): """ The Page object """ - id: typing.Optional[str] = pydantic.Field(default=None, description="Unique identifier for the Page") - site_id: typing.Optional[str] = pydantic.Field( - alias="siteId", default=None, description="Unique identifier for the Site" - ) - title: typing.Optional[str] = pydantic.Field(default=None, description="Title of the Page") - slug: typing.Optional[str] = pydantic.Field(default=None, description="slug of the Page (derived from title)") - parent_id: typing.Optional[str] = pydantic.Field( - alias="parentId", default=None, description="Identifier of the parent folder" - ) - collection_id: typing.Optional[str] = pydantic.Field( - alias="collectionId", - default=None, - description="Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection.", - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The date the Page was created" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="The date the Page was most recently updated" - ) - archived: typing.Optional[bool] = pydantic.Field(default=None, description="Whether the Page has been archived") - draft: typing.Optional[bool] = pydantic.Field(default=None, description="Whether the Page is a draft") - can_branch: typing.Optional[bool] = pydantic.Field( - alias="canBranch", - default=None, - description="Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching)", - ) - is_members_only: typing.Optional[bool] = pydantic.Field( - alias="isMembersOnly", - default=None, - description="Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions)", - ) - seo: typing.Optional[PageSeo] = pydantic.Field(default=None, description="SEO-related fields for the Page") - open_graph: typing.Optional[PageOpenGraph] = pydantic.Field( - alias="openGraph", default=None, description="Open Graph fields for the Page" - ) + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Unique identifier for the Page + """ + + site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + """ + Unique identifier for the Site + """ + + title: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Title of the Page + """ + + slug: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + slug of the Page (derived from title) + """ + + parent_id: typing.Optional[str] = pydantic_v1.Field(alias="parentId", default=None) + """ + Identifier of the parent folder + """ + + collection_id: typing.Optional[str] = pydantic_v1.Field(alias="collectionId", default=None) + """ + Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The date the Page was created + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + The date the Page was most recently updated + """ + + archived: typing.Optional[bool] = pydantic_v1.Field(default=None) + """ + Whether the Page has been archived + """ + + draft: typing.Optional[bool] = pydantic_v1.Field(default=None) + """ + Whether the Page is a draft + """ + + can_branch: typing.Optional[bool] = pydantic_v1.Field(alias="canBranch", default=None) + """ + Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) + """ + + is_members_only: typing.Optional[bool] = pydantic_v1.Field(alias="isMembersOnly", default=None) + """ + Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) + """ + + seo: typing.Optional[PageSeo] = pydantic_v1.Field(default=None) + """ + SEO-related fields for the Page + """ + + open_graph: typing.Optional[PageOpenGraph] = pydantic_v1.Field(alias="openGraph", default=None) + """ + Open Graph fields for the Page + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/page_details.py b/src/webflow/types/page_details.py new file mode 100644 index 0000000..6efa48e --- /dev/null +++ b/src/webflow/types/page_details.py @@ -0,0 +1,115 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from .page_details_open_graph import PageDetailsOpenGraph +from .page_details_seo import PageDetailsSeo + + +class PageDetails(pydantic_v1.BaseModel): + """ + The Page object + """ + + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Unique identifier for the Page + """ + + site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + """ + Unique identifier for the Site + """ + + title: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Title of the Page + """ + + slug: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + slug of the Page (derived from title) + """ + + parent_id: typing.Optional[str] = pydantic_v1.Field(alias="parentId", default=None) + """ + Identifier of the parent folder + """ + + collection_id: typing.Optional[str] = pydantic_v1.Field(alias="collectionId", default=None) + """ + Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The date the Page was created + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + The date the Page was most recently updated + """ + + archived: typing.Optional[bool] = pydantic_v1.Field(default=None) + """ + Whether the Page has been archived + """ + + draft: typing.Optional[bool] = pydantic_v1.Field(default=None) + """ + Whether the Page is a draft + """ + + can_branch: typing.Optional[bool] = pydantic_v1.Field(alias="canBranch", default=None) + """ + Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) + """ + + is_members_only: typing.Optional[bool] = pydantic_v1.Field(alias="isMembersOnly", default=None) + """ + Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) + """ + + seo: typing.Optional[PageDetailsSeo] = pydantic_v1.Field(default=None) + """ + SEO-related fields for the Page + """ + + open_graph: typing.Optional[PageDetailsOpenGraph] = pydantic_v1.Field(alias="openGraph", default=None) + """ + Open Graph fields for the Page + """ + + locale_id: typing.Optional[str] = pydantic_v1.Field(alias="localeId", default=None) + """ + Unique ID of the page locale + """ + + published_path: typing.Optional[str] = pydantic_v1.Field(alias="publishedPath", default=None) + """ + Relative path of the published page URL + """ + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/page_details_open_graph.py b/src/webflow/types/page_details_open_graph.py new file mode 100644 index 0000000..6d82c28 --- /dev/null +++ b/src/webflow/types/page_details_open_graph.py @@ -0,0 +1,53 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 + + +class PageDetailsOpenGraph(pydantic_v1.BaseModel): + """ + Open Graph fields for the Page + """ + + title: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The title supplied to Open Graph annotations + """ + + title_copied: typing.Optional[bool] = pydantic_v1.Field(alias="titleCopied", default=None) + """ + Indicates the Open Graph title was copied from the SEO title + """ + + description: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The description supplied to Open Graph annotations + """ + + description_copied: typing.Optional[bool] = pydantic_v1.Field(alias="descriptionCopied", default=None) + """ + Indicates the Open Graph description was copied from the SEO description + """ + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) + + class Config: + frozen = True + smart_union = True + allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/page_details_seo.py b/src/webflow/types/page_details_seo.py new file mode 100644 index 0000000..7038e39 --- /dev/null +++ b/src/webflow/types/page_details_seo.py @@ -0,0 +1,41 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 + + +class PageDetailsSeo(pydantic_v1.BaseModel): + """ + SEO-related fields for the Page + """ + + title: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The Page title shown in search engine results + """ + + description: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The Page description shown in search engine results + """ + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) + + class Config: + frozen = True + smart_union = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/page_list.py b/src/webflow/types/page_list.py index 3ba1a63..11c5420 100644 --- a/src/webflow/types/page_list.py +++ b/src/webflow/types/page_list.py @@ -4,16 +4,12 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .page import Page from .pagination import Pagination -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class PageList(pydantic.BaseModel): +class PageList(pydantic_v1.BaseModel): """ The Page object """ @@ -26,10 +22,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/page_open_graph.py b/src/webflow/types/page_open_graph.py index 2c7f5fb..317ba4b 100644 --- a/src/webflow/types/page_open_graph.py +++ b/src/webflow/types/page_open_graph.py @@ -4,43 +4,50 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class PageOpenGraph(pydantic.BaseModel): +class PageOpenGraph(pydantic_v1.BaseModel): """ Open Graph fields for the Page """ - title: typing.Optional[str] = pydantic.Field( - default=None, description="The title supplied to Open Graph annotations" - ) - title_copied: typing.Optional[bool] = pydantic.Field( - alias="titleCopied", default=None, description="Indicates the Open Graph title was copied from the SEO title" - ) - description: typing.Optional[str] = pydantic.Field( - default=None, description="The description supplied to Open Graph annotations" - ) - description_copied: typing.Optional[bool] = pydantic.Field( - alias="descriptionCopied", - default=None, - description="Indicates the Open Graph description was copied from the SEO description", - ) + title: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The title supplied to Open Graph annotations + """ + + title_copied: typing.Optional[bool] = pydantic_v1.Field(alias="titleCopied", default=None) + """ + Indicates the Open Graph title was copied from the SEO title + """ + + description: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The description supplied to Open Graph annotations + """ + + description_copied: typing.Optional[bool] = pydantic_v1.Field(alias="descriptionCopied", default=None) + """ + Indicates the Open Graph description was copied from the SEO description + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/page_seo.py b/src/webflow/types/page_seo.py index 091d1e9..02a9d3e 100644 --- a/src/webflow/types/page_seo.py +++ b/src/webflow/types/page_seo.py @@ -4,34 +4,38 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class PageSeo(pydantic.BaseModel): +class PageSeo(pydantic_v1.BaseModel): """ SEO-related fields for the Page """ - title: typing.Optional[str] = pydantic.Field( - default=None, description="The Page title shown in search engine results" - ) - description: typing.Optional[str] = pydantic.Field( - default=None, description="The Page description shown in search engine results" - ) + title: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The Page title shown in search engine results + """ + + description: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The Page description shown in search engine results + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/pagination.py b/src/webflow/types/pagination.py index b8bb3b6..16fed76 100644 --- a/src/webflow/types/pagination.py +++ b/src/webflow/types/pagination.py @@ -4,31 +4,43 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class Pagination(pydantic.BaseModel): +class Pagination(pydantic_v1.BaseModel): """ Pagination object """ - limit: typing.Optional[float] = pydantic.Field(default=None, description="The limit used for pagination") - offset: typing.Optional[float] = pydantic.Field(default=None, description="The offset used for pagination") - total: typing.Optional[float] = pydantic.Field(default=None, description="The total number of records") + limit: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The limit used for pagination + """ + + offset: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The offset used for pagination + """ + + total: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The total number of records + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/paypal_details.py b/src/webflow/types/paypal_details.py index 80afce3..3e8642c 100644 --- a/src/webflow/types/paypal_details.py +++ b/src/webflow/types/paypal_details.py @@ -4,43 +4,56 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class PaypalDetails(pydantic.BaseModel): - order_id: typing.Optional[str] = pydantic.Field( - alias="orderId", default=None, description="PayPal order identifier" - ) - payer_id: typing.Optional[str] = pydantic.Field( - alias="payerId", default=None, description="PayPal payer identifier" - ) - capture_id: typing.Optional[str] = pydantic.Field( - alias="captureId", default=None, description="PayPal capture identifier" - ) - refund_id: typing.Optional[str] = pydantic.Field( - alias="refundId", default=None, description="PayPal refund identifier" - ) - refund_reason: typing.Optional[str] = pydantic.Field( - alias="refundReason", default=None, description="PayPal-issued reason for the refund" - ) - dispute_id: typing.Optional[str] = pydantic.Field( - alias="disputeId", default=None, description="PayPal dispute identifier" - ) + +class PaypalDetails(pydantic_v1.BaseModel): + order_id: typing.Optional[str] = pydantic_v1.Field(alias="orderId", default=None) + """ + PayPal order identifier + """ + + payer_id: typing.Optional[str] = pydantic_v1.Field(alias="payerId", default=None) + """ + PayPal payer identifier + """ + + capture_id: typing.Optional[str] = pydantic_v1.Field(alias="captureId", default=None) + """ + PayPal capture identifier + """ + + refund_id: typing.Optional[str] = pydantic_v1.Field(alias="refundId", default=None) + """ + PayPal refund identifier + """ + + refund_reason: typing.Optional[str] = pydantic_v1.Field(alias="refundReason", default=None) + """ + PayPal-issued reason for the refund + """ + + dispute_id: typing.Optional[str] = pydantic_v1.Field(alias="disputeId", default=None) + """ + PayPal dispute identifier + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/product.py b/src/webflow/types/product.py index 81e7372..c557bd3 100644 --- a/src/webflow/types/product.py +++ b/src/webflow/types/product.py @@ -4,47 +4,68 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .product_field_data import ProductFieldData -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class Product(pydantic.BaseModel): +class Product(pydantic_v1.BaseModel): """ The Product object """ - id: typing.Optional[str] = pydantic.Field(default=None, description="Unique identifier for the Product") - last_published: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastPublished", default=None, description="The date the Product was last published" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="The date the Product was last updated" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The date the Product was created" - ) - is_archived: typing.Optional[bool] = pydantic.Field( - alias="isArchived", default=None, description="Boolean determining if the Product is set to archived" - ) - is_draft: typing.Optional[bool] = pydantic.Field( - alias="isDraft", default=None, description="Boolean determining if the Product is set to draft" - ) - field_data: typing.Optional[ProductFieldData] = pydantic.Field(alias="fieldData", default=None) + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Unique identifier for the Product + """ + + cms_locale_id: typing.Optional[str] = pydantic_v1.Field(alias="cmsLocaleId", default=None) + """ + Identifier for the locale of the CMS item + """ + + last_published: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastPublished", default=None) + """ + The date the Product was last published + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + The date the Product was last updated + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The date the Product was created + """ + + is_archived: typing.Optional[bool] = pydantic_v1.Field(alias="isArchived", default=None) + """ + Boolean determining if the Product is set to archived + """ + + is_draft: typing.Optional[bool] = pydantic_v1.Field(alias="isDraft", default=None) + """ + Boolean determining if the Product is set to draft + """ + + field_data: typing.Optional[ProductFieldData] = pydantic_v1.Field(alias="fieldData", default=None) def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/product_and_sk_us.py b/src/webflow/types/product_and_sk_us.py index 64ee6b5..eb9ab3d 100644 --- a/src/webflow/types/product_and_sk_us.py +++ b/src/webflow/types/product_and_sk_us.py @@ -4,32 +4,36 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .product import Product from .sku import Sku -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class ProductAndSkUs(pydantic.BaseModel): +class ProductAndSkUs(pydantic_v1.BaseModel): """ A product and its SKUs. """ product: typing.Optional[Product] = None - skus: typing.Optional[typing.List[Sku]] = pydantic.Field(default=None, description="A list of SKU Objects") + skus: typing.Optional[typing.List[Sku]] = pydantic_v1.Field(default=None) + """ + A list of SKU Objects + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/product_and_sk_us_list.py b/src/webflow/types/product_and_sk_us_list.py index 0c2eae5..db89130 100644 --- a/src/webflow/types/product_and_sk_us_list.py +++ b/src/webflow/types/product_and_sk_us_list.py @@ -4,24 +4,21 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .pagination import Pagination from .product_and_sk_us import ProductAndSkUs -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class ProductAndSkUsList(pydantic.BaseModel): +class ProductAndSkUsList(pydantic_v1.BaseModel): """ Results from product list """ - items: typing.Optional[typing.List[ProductAndSkUs]] = pydantic.Field( - default=None, - description="List of Item objects within the Collection. Contains product and skus keys for each Item", - ) + items: typing.Optional[typing.List[ProductAndSkUs]] = pydantic_v1.Field(default=None) + """ + List of Item objects within the Collection. Contains product and skus keys for each Item + """ + pagination: typing.Optional[Pagination] = None def json(self, **kwargs: typing.Any) -> str: @@ -29,10 +26,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/product_field_data.py b/src/webflow/types/product_field_data.py index 756c629..ac2db70 100644 --- a/src/webflow/types/product_field_data.py +++ b/src/webflow/types/product_field_data.py @@ -4,54 +4,82 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .product_field_data_ec_product_type import ProductFieldDataEcProductType from .product_field_data_tax_category import ProductFieldDataTaxCategory from .sku_property_list import SkuPropertyList -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class ProductFieldData(pydantic_v1.BaseModel): + """ + Contains content-specific details for a product, covering both standard (e.g., title, description) and custom fields tailored to the product setup. + """ -class ProductFieldData(pydantic.BaseModel): - name: str = pydantic.Field(description="Name of the Product") - slug: str = pydantic.Field(description="URL structure of the Product in your site.") - description: typing.Optional[str] = pydantic.Field(default=None, description="A description of your product") - shippable: typing.Optional[bool] = pydantic.Field( - default=None, description="Boolean determining if the Product is shippable" - ) - sku_properties: typing.Optional[typing.List[SkuPropertyList]] = pydantic.Field( - alias="sku-properties", default=None, description="Variant types to include in SKUs" - ) - categories: typing.Optional[typing.List[str]] = pydantic.Field( - default=None, description="The categories your product belongs to." - ) - tax_category: typing.Optional[ProductFieldDataTaxCategory] = pydantic.Field( - alias="tax-category", default=None, description="Product tax class" - ) - default_sku: typing.Optional[str] = pydantic.Field( - alias="default-sku", default=None, description="The default SKU associated with this product." - ) - ec_product_type: typing.Optional[ProductFieldDataEcProductType] = pydantic.Field( - alias="ec-product-type", - default=None, - description='Product types. Enums reflect the following values in order: Physical, Digital, Service, Advanced"', + name: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Name of the Product + """ + + slug: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + URL structure of the Product in your site. + """ + + description: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + A description of your product + """ + + shippable: typing.Optional[bool] = pydantic_v1.Field(default=None) + """ + Boolean determining if the Product is shippable + """ + + sku_properties: typing.Optional[typing.List[SkuPropertyList]] = pydantic_v1.Field( + alias="sku-properties", default=None ) - additional_properties: typing.Optional[str] = pydantic.Field( - alias="additionalProperties", default=None, description="Custom fields for your product." + """ + Variant types to include in SKUs + """ + + categories: typing.Optional[typing.List[str]] = pydantic_v1.Field(default=None) + """ + The categories your product belongs to. + """ + + tax_category: typing.Optional[ProductFieldDataTaxCategory] = pydantic_v1.Field(alias="tax-category", default=None) + """ + Product tax class + """ + + default_sku: typing.Optional[str] = pydantic_v1.Field(alias="default-sku", default=None) + """ + The default SKU associated with this product. + """ + + ec_product_type: typing.Optional[ProductFieldDataEcProductType] = pydantic_v1.Field( + alias="ec-product-type", default=None ) + """ + Product types. Enums reflect the following values in order: Physical, Digital, Service, Advanced" + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/registered_script_list.py b/src/webflow/types/registered_script_list.py index 96bcbaa..6ed8db3 100644 --- a/src/webflow/types/registered_script_list.py +++ b/src/webflow/types/registered_script_list.py @@ -4,16 +4,16 @@ import typing from ..core.datetime_utils import serialize_datetime -from .custom_code_response import CustomCodeResponse +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from .custom_code_hosted_response import CustomCodeHostedResponse -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class RegisteredScriptList(pydantic_v1.BaseModel): + """ + A list of scripts registered to the site + """ -class RegisteredScriptList(pydantic.BaseModel): - registered_scripts: typing.Optional[typing.List[CustomCodeResponse]] = pydantic.Field( + registered_scripts: typing.Optional[typing.List[CustomCodeHostedResponse]] = pydantic_v1.Field( alias="registeredScripts", default=None ) @@ -22,11 +22,17 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/script_apply.py b/src/webflow/types/script_apply.py index 2868113..38405ee 100644 --- a/src/webflow/types/script_apply.py +++ b/src/webflow/types/script_apply.py @@ -4,33 +4,45 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .script_apply_location import ScriptApplyLocation -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class ScriptApply(pydantic_v1.BaseModel): + id: str = pydantic_v1.Field() + """ + ID of the registered custom code script + """ -class ScriptApply(pydantic.BaseModel): - id: str = pydantic.Field(description="Id of the registered custom code script") - location: ScriptApplyLocation = pydantic.Field( - description="Location of the script, either in the header or footer of the published site" - ) - version: str = pydantic.Field(description="Semantic Version String for the registered script _e.g. 0.0.1_") - attributes: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field( - default=None, description="Developer-specified key/value pairs to be applied as attributes to the script" - ) + location: ScriptApplyLocation = pydantic_v1.Field() + """ + Location of the script, either in the header or footer of the published site + """ + + version: str = pydantic_v1.Field() + """ + Semantic Version String for the registered script _e.g. 0.0.1_ + """ + + attributes: typing.Optional[typing.Dict[str, typing.Any]] = pydantic_v1.Field(default=None) + """ + Developer-specified key/value pairs to be applied as attributes to the script + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/script_apply_list.py b/src/webflow/types/script_apply_list.py index 23e7579..46b1a69 100644 --- a/src/webflow/types/script_apply_list.py +++ b/src/webflow/types/script_apply_list.py @@ -4,33 +4,42 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .script_apply import ScriptApply -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class ScriptApplyList(pydantic_v1.BaseModel): + scripts: typing.Optional[typing.List[ScriptApply]] = pydantic_v1.Field(default=None) + """ + A list of scripts applied to a Site or a Page + """ -class ScriptApplyList(pydantic.BaseModel): - scripts: typing.Optional[typing.List[ScriptApply]] = None - last_updated: typing.Optional[str] = pydantic.Field( - alias="lastUpdated", default=None, description="Date when the Site's scripts were last updated" - ) - created_on: typing.Optional[str] = pydantic.Field( - alias="createdOn", default=None, description="Date when the Site's scripts were created" - ) + last_updated: typing.Optional[str] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + Date when the Site's scripts were last updated + """ + + created_on: typing.Optional[str] = pydantic_v1.Field(alias="createdOn", default=None) + """ + Date when the Site's scripts were created + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/site.py b/src/webflow/types/site.py index c1bba38..f00321f 100644 --- a/src/webflow/types/site.py +++ b/src/webflow/types/site.py @@ -4,52 +4,81 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .domain import Domain +from .locales import Locales -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class Site(pydantic.BaseModel): - id: str = pydantic.Field(description="Unique identifier for the Site") - workspace_id: typing.Optional[str] = pydantic.Field( - alias="workspaceId", default=None, description="Unique identifier for the Workspace" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="Date the Site was created" - ) - display_name: typing.Optional[str] = pydantic.Field( - alias="displayName", default=None, description="Name given to Site" - ) - short_name: typing.Optional[str] = pydantic.Field( - alias="shortName", default=None, description="Slugified version of name" - ) - last_published: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastPublished", default=None, description="Date the Site was last published" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="Date the Site was last updated" - ) - preview_url: typing.Optional[str] = pydantic.Field( - alias="previewUrl", default=None, description="URL of a generated image for the given Site" - ) - time_zone: typing.Optional[str] = pydantic.Field( - alias="timeZone", default=None, description="Site timezone set under Site Settings" - ) - custom_domains: typing.Optional[typing.List[Domain]] = pydantic.Field(alias="customDomains", default=None) + +class Site(pydantic_v1.BaseModel): + id: str = pydantic_v1.Field() + """ + Unique identifier for the Site + """ + + workspace_id: typing.Optional[str] = pydantic_v1.Field(alias="workspaceId", default=None) + """ + Unique identifier for the Workspace + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + Date the Site was created + """ + + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + """ + Name given to Site + """ + + short_name: typing.Optional[str] = pydantic_v1.Field(alias="shortName", default=None) + """ + Slugified version of name + """ + + last_published: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastPublished", default=None) + """ + Date the Site was last published + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + Date the Site was last updated + """ + + preview_url: typing.Optional[str] = pydantic_v1.Field(alias="previewUrl", default=None) + """ + URL of a generated image for the given Site + """ + + time_zone: typing.Optional[str] = pydantic_v1.Field(alias="timeZone", default=None) + """ + Site timezone set under Site Settings + """ + + parent_folder_id: typing.Optional[str] = pydantic_v1.Field(alias="parentFolderId", default=None) + """ + The ID of the parent folder the Site exists in + """ + + custom_domains: typing.Optional[typing.List[Domain]] = pydantic_v1.Field(alias="customDomains", default=None) + locales: typing.Optional[Locales] = None def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/site_activity_log_item.py b/src/webflow/types/site_activity_log_item.py index f04b804..a23608c 100644 --- a/src/webflow/types/site_activity_log_item.py +++ b/src/webflow/types/site_activity_log_item.py @@ -4,28 +4,24 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .site_activity_log_item_resource_operation import SiteActivityLogItemResourceOperation from .site_activity_log_item_user import SiteActivityLogItemUser -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class SiteActivityLogItem(pydantic.BaseModel): +class SiteActivityLogItem(pydantic_v1.BaseModel): id: typing.Optional[str] = None - created_on: typing.Optional[dt.datetime] = pydantic.Field(alias="createdOn", default=None) - last_updated: typing.Optional[dt.datetime] = pydantic.Field(alias="lastUpdated", default=None) + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) event: typing.Optional[str] = None - resource_operation: typing.Optional[SiteActivityLogItemResourceOperation] = pydantic.Field( + resource_operation: typing.Optional[SiteActivityLogItemResourceOperation] = pydantic_v1.Field( alias="resourceOperation", default=None ) user: typing.Optional[SiteActivityLogItemUser] = None - resource_id: typing.Optional[str] = pydantic.Field(alias="resourceId", default=None) - resource_name: typing.Optional[str] = pydantic.Field(alias="resourceName", default=None) - new_value: typing.Optional[str] = pydantic.Field(alias="newValue", default=None) - previous_value: typing.Optional[str] = pydantic.Field(alias="previousValue", default=None) + resource_id: typing.Optional[str] = pydantic_v1.Field(alias="resourceId", default=None) + resource_name: typing.Optional[str] = pydantic_v1.Field(alias="resourceName", default=None) + new_value: typing.Optional[str] = pydantic_v1.Field(alias="newValue", default=None) + previous_value: typing.Optional[str] = pydantic_v1.Field(alias="previousValue", default=None) payload: typing.Optional[typing.Dict[str, typing.Any]] = None def json(self, **kwargs: typing.Any) -> str: @@ -33,11 +29,17 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/site_activity_log_item_user.py b/src/webflow/types/site_activity_log_item_user.py index 66bcfbb..60e7846 100644 --- a/src/webflow/types/site_activity_log_item_user.py +++ b/src/webflow/types/site_activity_log_item_user.py @@ -4,27 +4,29 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class SiteActivityLogItemUser(pydantic.BaseModel): +class SiteActivityLogItemUser(pydantic_v1.BaseModel): id: typing.Optional[str] = None - display_name: typing.Optional[str] = pydantic.Field(alias="displayName", default=None) + display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/site_activity_log_response.py b/src/webflow/types/site_activity_log_response.py index 06a04ab..69bcc31 100644 --- a/src/webflow/types/site_activity_log_response.py +++ b/src/webflow/types/site_activity_log_response.py @@ -4,16 +4,12 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .pagination import Pagination from .site_activity_log_item import SiteActivityLogItem -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class SiteActivityLogResponse(pydantic.BaseModel): +class SiteActivityLogResponse(pydantic_v1.BaseModel): items: typing.Optional[typing.List[SiteActivityLogItem]] = None pagination: typing.Optional[Pagination] = None @@ -22,10 +18,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/sites.py b/src/webflow/types/sites.py new file mode 100644 index 0000000..18a9338 --- /dev/null +++ b/src/webflow/types/sites.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from .site import Site + + +class Sites(pydantic_v1.BaseModel): + sites: typing.Optional[typing.List[Site]] = None + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) + + class Config: + frozen = True + smart_union = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/sku.py b/src/webflow/types/sku.py index a97ee15..ae2008e 100644 --- a/src/webflow/types/sku.py +++ b/src/webflow/types/sku.py @@ -4,43 +4,58 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .sku_field_data import SkuFieldData -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class Sku(pydantic.BaseModel): +class Sku(pydantic_v1.BaseModel): """ The SKU object """ - id: typing.Optional[str] = pydantic.Field(default=None, description="Unique identifier for the Product") - last_published: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastPublished", default=None, description="The date the Product was last published" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="The date the Product was last updated" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The date the Product was created" - ) - field_data: typing.Optional[SkuFieldData] = pydantic.Field( - alias="fieldData", default=None, description="Standard and Custom fields for a SKU" - ) + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Unique identifier for the Product + """ + + cms_locale_id: typing.Optional[str] = pydantic_v1.Field(alias="cmsLocaleId", default=None) + """ + Identifier for the locale of the CMS item + """ + + last_published: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastPublished", default=None) + """ + The date the Product was last published + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + The date the Product was last updated + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The date the Product was created + """ + + field_data: typing.Optional[SkuFieldData] = pydantic_v1.Field(alias="fieldData", default=None) def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/sku_field_data.py b/src/webflow/types/sku_field_data.py index 7143bc3..d90c09d 100644 --- a/src/webflow/types/sku_field_data.py +++ b/src/webflow/types/sku_field_data.py @@ -4,55 +4,74 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .sku_field_data_compare_at_price import SkuFieldDataCompareAtPrice from .sku_field_data_ec_sku_billing_method import SkuFieldDataEcSkuBillingMethod from .sku_field_data_ec_sku_subscription_plan import SkuFieldDataEcSkuSubscriptionPlan from .sku_field_data_price import SkuFieldDataPrice from .sku_value_list import SkuValueList -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class SkuFieldData(pydantic.BaseModel): +class SkuFieldData(pydantic_v1.BaseModel): """ Standard and Custom fields for a SKU """ - sku_values: typing.Optional[SkuValueList] = pydantic.Field(alias="sku-values", default=None) - name: str = pydantic.Field(description="Name of the Product") - slug: str = pydantic.Field(description="URL structure of the Product in your site.") - price: SkuFieldDataPrice = pydantic.Field(description="price of SKU") - compare_at_price: typing.Optional[SkuFieldDataCompareAtPrice] = pydantic.Field( - alias="compare-at-price", default=None, description="comparison price of SKU" + sku_values: typing.Optional[SkuValueList] = pydantic_v1.Field(alias="sku-values", default=None) + name: str = pydantic_v1.Field() + """ + Name of the Product + """ + + slug: str = pydantic_v1.Field() + """ + URL structure of the Product in your site. + """ + + price: SkuFieldDataPrice = pydantic_v1.Field() + """ + price of SKU + """ + + compare_at_price: typing.Optional[SkuFieldDataCompareAtPrice] = pydantic_v1.Field( + alias="compare-at-price", default=None ) - ec_sku_billing_method: typing.Optional[SkuFieldDataEcSkuBillingMethod] = pydantic.Field( + """ + comparison price of SKU + """ + + ec_sku_billing_method: typing.Optional[SkuFieldDataEcSkuBillingMethod] = pydantic_v1.Field( alias="ec-sku-billing-method", default=None ) - ec_sku_subscription_plan: typing.Optional[SkuFieldDataEcSkuSubscriptionPlan] = pydantic.Field( + ec_sku_subscription_plan: typing.Optional[SkuFieldDataEcSkuSubscriptionPlan] = pydantic_v1.Field( alias="ec-sku-subscription-plan", default=None ) - track_inventory: typing.Optional[bool] = pydantic.Field( - alias="track-inventory", - default=None, - description="A boolean indicating whether inventory for this product should be tracked.", - ) - quantity: typing.Optional[float] = pydantic.Field( - default=None, description="Quantity of SKU that will be tracked as items are ordered." - ) + track_inventory: typing.Optional[bool] = pydantic_v1.Field(alias="track-inventory", default=None) + """ + A boolean indicating whether inventory for this product should be tracked. + """ + + quantity: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Quantity of SKU that will be tracked as items are ordered. + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/sku_field_data_compare_at_price.py b/src/webflow/types/sku_field_data_compare_at_price.py index 6b85f7a..2a72eb0 100644 --- a/src/webflow/types/sku_field_data_compare_at_price.py +++ b/src/webflow/types/sku_field_data_compare_at_price.py @@ -4,30 +4,38 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class SkuFieldDataCompareAtPrice(pydantic.BaseModel): +class SkuFieldDataCompareAtPrice(pydantic_v1.BaseModel): """ comparison price of SKU """ - value: typing.Optional[float] = pydantic.Field(default=None, description="Price of SKU") - unit: typing.Optional[str] = pydantic.Field(default=None, description="Currency of Item") + value: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Price of SKU + """ + + unit: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Currency of Item + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py b/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py index e69bcb4..cc9e529 100644 --- a/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py +++ b/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py @@ -4,30 +4,43 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .sku_field_data_ec_sku_subscription_plan_interval import SkuFieldDataEcSkuSubscriptionPlanInterval +from .sku_field_data_ec_sku_subscription_plan_plans_item import SkuFieldDataEcSkuSubscriptionPlanPlansItem -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore +class SkuFieldDataEcSkuSubscriptionPlan(pydantic_v1.BaseModel): + interval: typing.Optional[SkuFieldDataEcSkuSubscriptionPlanInterval] = pydantic_v1.Field(default=None) + """ + Interval of subscription renewal + """ -class SkuFieldDataEcSkuSubscriptionPlan(pydantic.BaseModel): - interval: typing.Optional[SkuFieldDataEcSkuSubscriptionPlanInterval] = pydantic.Field( - default=None, description="Interval of subscription renewal" - ) - frequency: typing.Optional[float] = pydantic.Field(default=None, description="Frequncy of billing within interval") - trial: typing.Optional[float] = pydantic.Field(default=None, description="Number of days of a trial") + frequency: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Frequncy of billing within interval + """ + + trial: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Number of days of a trial + """ + + plans: typing.Optional[typing.List[SkuFieldDataEcSkuSubscriptionPlanPlansItem]] = None def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py new file mode 100644 index 0000000..074cc7a --- /dev/null +++ b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py @@ -0,0 +1,43 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from .sku_field_data_ec_sku_subscription_plan_plans_item_status import SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus + + +class SkuFieldDataEcSkuSubscriptionPlanPlansItem(pydantic_v1.BaseModel): + platform: typing.Optional[typing.Literal["stripe"]] = pydantic_v1.Field(default=None) + """ + The platform of the subscription plan + """ + + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The unique identifier of the plan + """ + + status: typing.Optional[SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus] = pydantic_v1.Field(default=None) + """ + The status of the plan + """ + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) + + class Config: + frozen = True + smart_union = True + extra = pydantic_v1.Extra.allow + json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item_status.py b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item_status.py new file mode 100644 index 0000000..d5daba6 --- /dev/null +++ b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item_status.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus(str, enum.Enum): + """ + The status of the plan + """ + + ACTIVE = "active" + INACTIVE = "inactive" + CANCELED = "canceled" + + def visit( + self, + active: typing.Callable[[], T_Result], + inactive: typing.Callable[[], T_Result], + canceled: typing.Callable[[], T_Result], + ) -> T_Result: + if self is SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus.ACTIVE: + return active() + if self is SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus.INACTIVE: + return inactive() + if self is SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus.CANCELED: + return canceled() diff --git a/src/webflow/types/sku_field_data_price.py b/src/webflow/types/sku_field_data_price.py index a588035..e72419b 100644 --- a/src/webflow/types/sku_field_data_price.py +++ b/src/webflow/types/sku_field_data_price.py @@ -4,30 +4,38 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class SkuFieldDataPrice(pydantic.BaseModel): +class SkuFieldDataPrice(pydantic_v1.BaseModel): """ price of SKU """ - value: typing.Optional[float] = pydantic.Field(default=None, description="Price of SKU") - unit: typing.Optional[str] = pydantic.Field(default=None, description="Currency of Item") + value: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Price of SKU + """ + + unit: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Currency of Item + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/sku_property_list.py b/src/webflow/types/sku_property_list.py index 68acf4a..85093e9 100644 --- a/src/webflow/types/sku_property_list.py +++ b/src/webflow/types/sku_property_list.py @@ -4,34 +4,44 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .sku_property_list_enum_item import SkuPropertyListEnumItem -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class SkuPropertyList(pydantic.BaseModel): +class SkuPropertyList(pydantic_v1.BaseModel): """ A variant/option type for a SKU """ - id: str = pydantic.Field(description="Unique identifier for a collection of Product Variants") - name: str = pydantic.Field(description="Name of the collection of Product Variants") - enum: typing.List[SkuPropertyListEnumItem] = pydantic.Field( - description="The individual Product variants that are contained within the collection" - ) + id: str = pydantic_v1.Field() + """ + Unique identifier for a collection of Product Variants + """ + + name: str = pydantic_v1.Field() + """ + Name of the collection of Product Variants + """ + + enum: typing.List[SkuPropertyListEnumItem] = pydantic_v1.Field() + """ + The individual Product variants that are contained within the collection + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/sku_property_list_enum_item.py b/src/webflow/types/sku_property_list_enum_item.py index e995e4a..6a26009 100644 --- a/src/webflow/types/sku_property_list_enum_item.py +++ b/src/webflow/types/sku_property_list_enum_item.py @@ -4,31 +4,43 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class SkuPropertyListEnumItem(pydantic.BaseModel): +class SkuPropertyListEnumItem(pydantic_v1.BaseModel): """ Enumerated Product variants/Options for the SKU """ - id: str = pydantic.Field(description="Unique identifier for a Product variant/Option") - name: str = pydantic.Field(description="Name of the Product variant/Option") - slug: str = pydantic.Field(description="Slug for the Product variant/Option in the Site URL structure") + id: str = pydantic_v1.Field() + """ + Unique identifier for a Product variant/Option + """ + + name: str = pydantic_v1.Field() + """ + Name of the Product variant/Option + """ + + slug: str = pydantic_v1.Field() + """ + Slug for the Product variant/Option in the Site URL structure + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/stripe_card.py b/src/webflow/types/stripe_card.py index deb17d0..a6ba3f2 100644 --- a/src/webflow/types/stripe_card.py +++ b/src/webflow/types/stripe_card.py @@ -4,43 +4,52 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .stripe_card_brand import StripeCardBrand from .stripe_card_expires import StripeCardExpires -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class StripeCard(pydantic.BaseModel): +class StripeCard(pydantic_v1.BaseModel): """ Details on the card used to fulfill this order, if this order was finalized with Stripe. """ - last_4: typing.Optional[str] = pydantic.Field( - alias="last4", default=None, description="The last 4 digits on the card as a string" - ) - brand: typing.Optional[StripeCardBrand] = pydantic.Field( - default=None, description="The card's brand (ie. credit card network)" - ) - owner_name: typing.Optional[str] = pydantic.Field( - alias="ownerName", default=None, description="The name on the card." - ) - expires: typing.Optional[StripeCardExpires] = pydantic.Field( - default=None, description="The card's expiration date." - ) + last_4: typing.Optional[str] = pydantic_v1.Field(alias="last4", default=None) + """ + The last 4 digits on the card as a string + """ + + brand: typing.Optional[StripeCardBrand] = pydantic_v1.Field(default=None) + """ + The card's brand (ie. credit card network) + """ + + owner_name: typing.Optional[str] = pydantic_v1.Field(alias="ownerName", default=None) + """ + The name on the card. + """ + + expires: typing.Optional[StripeCardExpires] = pydantic_v1.Field(default=None) + """ + The card's expiration date. + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/stripe_card_expires.py b/src/webflow/types/stripe_card_expires.py index 793f717..b3eb064 100644 --- a/src/webflow/types/stripe_card_expires.py +++ b/src/webflow/types/stripe_card_expires.py @@ -4,30 +4,38 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class StripeCardExpires(pydantic.BaseModel): +class StripeCardExpires(pydantic_v1.BaseModel): """ The card's expiration date. """ - year: typing.Optional[float] = pydantic.Field(default=None, description="Year that the card expires") - month: typing.Optional[float] = pydantic.Field(default=None, description="Month that the card expires") + year: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Year that the card expires + """ + + month: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Month that the card expires + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/stripe_details.py b/src/webflow/types/stripe_details.py index e71a90d..3c03e22 100644 --- a/src/webflow/types/stripe_details.py +++ b/src/webflow/types/stripe_details.py @@ -4,53 +4,70 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class StripeDetails(pydantic.BaseModel): +class StripeDetails(pydantic_v1.BaseModel): """ An object with various Stripe IDs, useful for linking into the stripe dashboard. """ - subscription_id: typing.Optional[str] = pydantic.Field( - alias="subscriptionId", default=None, description="Stripe-generated identifier for the Subscription" - ) - payment_method: typing.Optional[str] = pydantic.Field( - alias="paymentMethod", default=None, description="Stripe-generated identifier for the PaymentMethod used" - ) - payment_intent_id: typing.Optional[str] = pydantic.Field( - alias="paymentIntentId", default=None, description="Stripe-generated identifier for the PaymentIntent, or null" - ) - customer_id: typing.Optional[str] = pydantic.Field( - alias="customerId", default=None, description="Stripe-generated customer identifier, or null" - ) - charge_id: typing.Optional[str] = pydantic.Field( - alias="chargeId", default=None, description="Stripe-generated charge identifier, or null" - ) - dispute_id: typing.Optional[str] = pydantic.Field( - alias="disputeId", default=None, description="Stripe-generated dispute identifier, or null" - ) - refund_id: typing.Optional[str] = pydantic.Field( - alias="refundId", default=None, description="Stripe-generated refund identifier, or null" - ) - refund_reason: typing.Optional[str] = pydantic.Field( - alias="refundReason", default=None, description="Stripe-generated refund reason, or null" - ) + subscription_id: typing.Optional[str] = pydantic_v1.Field(alias="subscriptionId", default=None) + """ + Stripe-generated identifier for the Subscription + """ + + payment_method: typing.Optional[str] = pydantic_v1.Field(alias="paymentMethod", default=None) + """ + Stripe-generated identifier for the PaymentMethod used + """ + + payment_intent_id: typing.Optional[str] = pydantic_v1.Field(alias="paymentIntentId", default=None) + """ + Stripe-generated identifier for the PaymentIntent, or null + """ + + customer_id: typing.Optional[str] = pydantic_v1.Field(alias="customerId", default=None) + """ + Stripe-generated customer identifier, or null + """ + + charge_id: typing.Optional[str] = pydantic_v1.Field(alias="chargeId", default=None) + """ + Stripe-generated charge identifier, or null + """ + + dispute_id: typing.Optional[str] = pydantic_v1.Field(alias="disputeId", default=None) + """ + Stripe-generated dispute identifier, or null + """ + + refund_id: typing.Optional[str] = pydantic_v1.Field(alias="refundId", default=None) + """ + Stripe-generated refund identifier, or null + """ + + refund_reason: typing.Optional[str] = pydantic_v1.Field(alias="refundReason", default=None) + """ + Stripe-generated refund reason, or null + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/text_node.py b/src/webflow/types/text_node.py index e0b9aac..a6a7a6d 100644 --- a/src/webflow/types/text_node.py +++ b/src/webflow/types/text_node.py @@ -4,14 +4,10 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class TextNode(pydantic.BaseModel): +class TextNode(pydantic_v1.BaseModel): """ Represents textual content within the DOM. It contains both the raw text and its HTML representation, allowing for flexibility in rendering and processing. Additional attributes can be associated with the text for styling or other purposes. """ @@ -24,10 +20,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/user.py b/src/webflow/types/user.py index ec54559..c443c97 100644 --- a/src/webflow/types/user.py +++ b/src/webflow/types/user.py @@ -4,41 +4,59 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .user_access_groups_item import UserAccessGroupsItem from .user_data import UserData from .user_status import UserStatus -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class User(pydantic.BaseModel): +class User(pydantic_v1.BaseModel): """ The fields that define the schema for a given Item are based on the Collection that Item belongs to. Beyond the user defined fields, there are a handful of additional fields that are automatically created for all items """ - id: typing.Optional[str] = pydantic.Field(default=None, description="Unique identifier for the User") - is_email_verified: typing.Optional[bool] = pydantic.Field( - alias="isEmailVerified", default=None, description="Shows whether the user has verified their email address" - ) - last_updated: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastUpdated", default=None, description="The timestamp the user was updated" - ) - invited_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="invitedOn", default=None, description="The timestamp the user was invited" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="The timestamp the user was created" - ) - last_login: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastLogin", default=None, description="The timestamp the user was logged in" - ) - status: typing.Optional[UserStatus] = pydantic.Field(default=None, description="The status of the user") - access_groups: typing.Optional[typing.List[UserAccessGroupsItem]] = pydantic.Field( - alias="accessGroups", default=None, description="Access groups the user belongs to" + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Unique identifier for the User + """ + + is_email_verified: typing.Optional[bool] = pydantic_v1.Field(alias="isEmailVerified", default=None) + """ + Shows whether the user has verified their email address + """ + + last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + """ + The timestamp the user was updated + """ + + invited_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="invitedOn", default=None) + """ + The timestamp the user was invited + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + The timestamp the user was created + """ + + last_login: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastLogin", default=None) + """ + The timestamp the user was logged in + """ + + status: typing.Optional[UserStatus] = pydantic_v1.Field(default=None) + """ + The status of the user + """ + + access_groups: typing.Optional[typing.List[UserAccessGroupsItem]] = pydantic_v1.Field( + alias="accessGroups", default=None ) + """ + Access groups the user belongs to + """ + data: typing.Optional[UserData] = None def json(self, **kwargs: typing.Any) -> str: @@ -46,11 +64,17 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/user_access_groups_item.py b/src/webflow/types/user_access_groups_item.py index 7eeb0f7..61aa168 100644 --- a/src/webflow/types/user_access_groups_item.py +++ b/src/webflow/types/user_access_groups_item.py @@ -4,39 +4,42 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .user_access_groups_item_type import UserAccessGroupsItemType -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class UserAccessGroupsItem(pydantic.BaseModel): +class UserAccessGroupsItem(pydantic_v1.BaseModel): """ Access group slugs and types """ - slug: typing.Optional[str] = pydantic.Field(default=None, description="Access group identifier for APIs") - type: typing.Optional[UserAccessGroupsItemType] = pydantic.Field( - default=None, - description=( - "The type of access group based on how it was assigned to the user.\n" - "\n" - "- `admin` - Assigned to the user via API or in the designer\n" - "- `ecommerce` - Assigned to the user via an ecommerce purchase\n" - ), - ) + slug: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Access group identifier for APIs + """ + + type: typing.Optional[UserAccessGroupsItemType] = pydantic_v1.Field(default=None) + """ + The type of access group based on how it was assigned to the user. + + - `admin` - Assigned to the user via API or in the designer + - `ecommerce` - Assigned to the user via an ecommerce purchase + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/user_data.py b/src/webflow/types/user_data.py index d28d82e..0813b37 100644 --- a/src/webflow/types/user_data.py +++ b/src/webflow/types/user_data.py @@ -4,15 +4,11 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .user_data_data import UserDataData -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class UserData(pydantic.BaseModel): +class UserData(pydantic_v1.BaseModel): """ An object containing the User's basic info and custom fields """ @@ -24,10 +20,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/user_data_data.py b/src/webflow/types/user_data_data.py index b58ade7..0366831 100644 --- a/src/webflow/types/user_data_data.py +++ b/src/webflow/types/user_data_data.py @@ -4,40 +4,51 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class UserDataData(pydantic.BaseModel): - name: typing.Optional[str] = pydantic.Field(default=None, description="The name of the user") - email: typing.Optional[str] = pydantic.Field(default=None, description="The email address of the user") - accept_privacy: typing.Optional[bool] = pydantic.Field( - alias="accept-privacy", - default=None, - description="Boolean indicating if the user has accepted the privacy policy", - ) - accept_communications: typing.Optional[bool] = pydantic.Field( - alias="accept-communications", - default=None, - description="Boolean indicating if the user has accepted to receive communications", - ) - additional_properties: typing.Optional[str] = pydantic.Field( - alias="additionalProperties", default=None, description="Custom user attributes" - ) + +class UserDataData(pydantic_v1.BaseModel): + name: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The name of the user + """ + + email: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + The email address of the user + """ + + accept_privacy: typing.Optional[bool] = pydantic_v1.Field(alias="accept-privacy", default=None) + """ + Boolean indicating if the user has accepted the privacy policy + """ + + accept_communications: typing.Optional[bool] = pydantic_v1.Field(alias="accept-communications", default=None) + """ + Boolean indicating if the user has accepted to receive communications + """ + + additional_properties: typing.Optional[str] = pydantic_v1.Field(alias="additionalProperties", default=None) + """ + Custom user attributes + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/user_limit_reached.py b/src/webflow/types/user_limit_reached.py index e5685fe..62b0412 100644 --- a/src/webflow/types/user_limit_reached.py +++ b/src/webflow/types/user_limit_reached.py @@ -1,37 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt -import typing +from .error import Error -from ..core.datetime_utils import serialize_datetime -from .error_details_item import ErrorDetailsItem - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class UserLimitReached(pydantic.BaseModel): - code: typing.Optional[str] = pydantic.Field(default=None, description="Error code") - message: typing.Optional[str] = pydantic.Field(default=None, description="Error message") - external_reference: typing.Optional[str] = pydantic.Field( - alias="externalReference", default=None, description="Link to more information" - ) - details: typing.Optional[typing.List[ErrorDetailsItem]] = pydantic.Field( - default=None, description="Array of errors" - ) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - json_encoders = {dt.datetime: serialize_datetime} +UserLimitReached = Error diff --git a/src/webflow/types/user_list.py b/src/webflow/types/user_list.py index 5c2b5a2..ff1732d 100644 --- a/src/webflow/types/user_list.py +++ b/src/webflow/types/user_list.py @@ -4,34 +4,54 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .user import User -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class UserList(pydantic.BaseModel): +class UserList(pydantic_v1.BaseModel): """ The list users results """ - count: typing.Optional[float] = pydantic.Field(default=None, description="Number of users returned") - limit: typing.Optional[float] = pydantic.Field(default=None, description="The limit specified in the request") - offset: typing.Optional[float] = pydantic.Field(default=None, description="The offset specified for pagination") - total: typing.Optional[float] = pydantic.Field(default=None, description="Total number of users in the collection") - users: typing.Optional[typing.List[User]] = pydantic.Field(default=None, description="List of Users for a Site") + count: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Number of users returned + """ + + limit: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The limit specified in the request + """ + + offset: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + The offset specified for pagination + """ + + total: typing.Optional[float] = pydantic_v1.Field(default=None) + """ + Total number of users in the collection + """ + + users: typing.Optional[typing.List[User]] = pydantic_v1.Field(default=None) + """ + List of Users for a Site + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/users_not_enabled.py b/src/webflow/types/users_not_enabled.py index c2959c6..2d9b8d6 100644 --- a/src/webflow/types/users_not_enabled.py +++ b/src/webflow/types/users_not_enabled.py @@ -1,37 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt -import typing +from .error import Error -from ..core.datetime_utils import serialize_datetime -from .error_details_item import ErrorDetailsItem - -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class UsersNotEnabled(pydantic.BaseModel): - code: typing.Optional[str] = pydantic.Field(default=None, description="Error code") - message: typing.Optional[str] = pydantic.Field(default=None, description="Error message") - external_reference: typing.Optional[str] = pydantic.Field( - alias="externalReference", default=None, description="Link to more information" - ) - details: typing.Optional[typing.List[ErrorDetailsItem]] = pydantic.Field( - default=None, description="Array of errors" - ) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - json_encoders = {dt.datetime: serialize_datetime} +UsersNotEnabled = Error diff --git a/src/webflow/types/webhook.py b/src/webflow/types/webhook.py index 29dff3c..9697dfb 100644 --- a/src/webflow/types/webhook.py +++ b/src/webflow/types/webhook.py @@ -4,49 +4,63 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .trigger_type import TriggerType -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - - -class Webhook(pydantic.BaseModel): - id: typing.Optional[str] = pydantic.Field( - default=None, description="Unique identifier for the Webhook registration" - ) - workspace_id: typing.Optional[str] = pydantic.Field( - alias="workspaceId", - default=None, - description="Unique identifier for the Workspace the Webhook is registered in", - ) - site_id: typing.Optional[str] = pydantic.Field( - alias="siteId", default=None, description="Unique identifier for the Site the Webhook is registered in" - ) - trigger_type: typing.Optional[TriggerType] = pydantic.Field(alias="triggerType", default=None) - filter: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field( - default=None, - description="Filter for selecting which events you want Webhooks to be sent for. Only supported for form_submission trigger types.", - ) - last_triggered: typing.Optional[dt.datetime] = pydantic.Field( - alias="lastTriggered", default=None, description="Date the Webhook instance was last triggered" - ) - created_on: typing.Optional[dt.datetime] = pydantic.Field( - alias="createdOn", default=None, description="Date the Webhook registration was created" - ) - url: typing.Optional[str] = pydantic.Field(default=None, description="URL to send the Webhook payload to") + +class Webhook(pydantic_v1.BaseModel): + id: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + Unique identifier for the Webhook registration + """ + + workspace_id: typing.Optional[str] = pydantic_v1.Field(alias="workspaceId", default=None) + """ + Unique identifier for the Workspace the Webhook is registered in + """ + + site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + """ + Unique identifier for the Site the Webhook is registered in + """ + + trigger_type: typing.Optional[TriggerType] = pydantic_v1.Field(alias="triggerType", default=None) + filter: typing.Optional[typing.Dict[str, typing.Any]] = pydantic_v1.Field(default=None) + """ + Filter for selecting which events you want Webhooks to be sent for. Only supported for form_submission trigger types. + """ + + last_triggered: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastTriggered", default=None) + """ + Date the Webhook instance was last triggered + """ + + created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + """ + Date the Webhook registration was created + """ + + url: typing.Optional[str] = pydantic_v1.Field(default=None) + """ + URL to send the Webhook payload to + """ def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True allow_population_by_field_name = True + populate_by_name = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/webhook_list.py b/src/webflow/types/webhook_list.py index 62f5dd2..d55f417 100644 --- a/src/webflow/types/webhook_list.py +++ b/src/webflow/types/webhook_list.py @@ -4,16 +4,12 @@ import typing from ..core.datetime_utils import serialize_datetime +from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .pagination import Pagination from .webhook import Webhook -try: - import pydantic.v1 as pydantic # type: ignore -except ImportError: - import pydantic # type: ignore - -class WebhookList(pydantic.BaseModel): +class WebhookList(pydantic_v1.BaseModel): pagination: typing.Optional[Pagination] = None webhooks: typing.Optional[typing.List[Webhook]] = None @@ -22,10 +18,15 @@ def json(self, **kwargs: typing.Any) -> str: return super().json(**kwargs_with_defaults) def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().dict(**kwargs_with_defaults) + kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} + kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + + return deep_union_pydantic_dicts( + super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) + ) class Config: frozen = True smart_union = True + extra = pydantic_v1.Extra.allow json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/version.py b/src/webflow/version.py new file mode 100644 index 0000000..c84c3e9 --- /dev/null +++ b/src/webflow/version.py @@ -0,0 +1,4 @@ + +from importlib import metadata + +__version__ = metadata.version("webflow") diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_client.py b/tests/custom/test_client.py similarity index 100% rename from tests/test_client.py rename to tests/custom/test_client.py diff --git a/tests/utils/test_http_client.py b/tests/utils/test_http_client.py new file mode 100644 index 0000000..98fd3c9 --- /dev/null +++ b/tests/utils/test_http_client.py @@ -0,0 +1,47 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow.core.http_client import get_request_body +from webflow.core.request_options import RequestOptions + + +def get_request_options() -> RequestOptions: + return {"additional_body_parameters": {"see you": "later"}} + + +def test_get_json_request_body() -> None: + json_body, data_body = get_request_body(json={"hello": "world"}, data=None, request_options=None, omit=None) + assert json_body == {"hello": "world"} + assert data_body is None + + json_body_extras, data_body_extras = get_request_body( + json={"goodbye": "world"}, data=None, request_options=get_request_options(), omit=None + ) + + assert json_body_extras == {"goodbye": "world", "see you": "later"} + assert data_body_extras is None + + +def test_get_files_request_body() -> None: + json_body, data_body = get_request_body(json=None, data={"hello": "world"}, request_options=None, omit=None) + assert data_body == {"hello": "world"} + assert json_body is None + + json_body_extras, data_body_extras = get_request_body( + json=None, data={"goodbye": "world"}, request_options=get_request_options(), omit=None + ) + + assert data_body_extras == {"goodbye": "world", "see you": "later"} + assert json_body_extras is None + + +def test_get_none_request_body() -> None: + json_body, data_body = get_request_body(json=None, data=None, request_options=None, omit=None) + assert data_body is None + assert json_body is None + + json_body_extras, data_body_extras = get_request_body( + json=None, data=None, request_options=get_request_options(), omit=None + ) + + assert json_body_extras == {"see you": "later"} + assert data_body_extras is None diff --git a/tests/utils/test_query_encoding.py b/tests/utils/test_query_encoding.py new file mode 100644 index 0000000..a5d083e --- /dev/null +++ b/tests/utils/test_query_encoding.py @@ -0,0 +1,13 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow.core.query_encoder import encode_query + + +def test_query_encoding() -> None: + assert encode_query({"hello world": "hello world"}) == {"hello world": "hello world"} + assert encode_query({"hello_world": {"hello": "world"}}) == {"hello_world[hello]": "world"} + assert encode_query({"hello_world": {"hello": {"world": "today"}, "test": "this"}, "hi": "there"}) == { + "hello_world[hello][world]": "today", + "hello_world[test]": "this", + "hi": "there", + } From 5712e231c2c542e4dccf9ca6e918864d3a115942 Mon Sep 17 00:00:00 2001 From: Zach Plata Date: Wed, 11 Dec 2024 10:57:40 -0600 Subject: [PATCH 02/13] docs: update README.md links and image --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5bd81ef..e6cc6cc 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![fern shield](https://img.shields.io/badge/%F0%9F%8C%BF-SDK%20generated%20by%20Fern-brightgreen)](https://github.com/fern-api/fern) [![pypi](https://img.shields.io/pypi/v/webflow.svg)](https://pypi.python.org/pypi/webflow) -The Webflow Python Library provides convenient access to the [Webflow Data API](https://developers.webflow.com/reference/rest-introduction) from +The Webflow Python Library provides convenient access to the [Webflow Data API](https://developers.webflow.com/data/reference/rest-introduction) from applications written in Python. The library includes type definitions for all @@ -55,12 +55,12 @@ asyncio.run(main()) ## OAuth -To implement OAuth, you'll need to [register a Webflow App in your Workspace](https://developers.webflow.com/reference/authorization) +To implement OAuth, you'll need to [register a Webflow App in your Workspace](https://developers.webflow.com/data/reference/authentication) ### Step 1: Authorize URL The first step in OAuth is to generate an Authorization URL. Use this URL -to fetch your Authorization Code. See the [docs](https://docs.developers.webflow.com/v1.0.0/docs/oauth#user-authorization) +to fetch your Authorization Code. See the [docs](https://developers.webflow.com/data/reference/oauth-app#2-create-an-authorization-link) for more details. ```python @@ -106,7 +106,7 @@ client = Webflow( All of the models are nested within the Webflow module. Let IntelliSense guide you! -![Alt text](assets/module.png) +![Use IntelliSense to guide API usage](https://raw.githubusercontent.com/webflow/webflow-python/main/assets/module.png) ## Exception Handling All errors thrown by the SDK will be subclasses of [`ApiError`](./src/webflow/core/api_error.py). From 152eccd1f8055f830bb1dcc5a57440fd5dcd98da Mon Sep 17 00:00:00 2001 From: Zach Plata Date: Fri, 21 Feb 2025 14:00:35 -0600 Subject: [PATCH 03/13] fix: update ubuntu image on ci --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb1b2d3..7c312a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: ci on: [push] jobs: compile: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Checkout repo uses: actions/checkout@v3 @@ -19,7 +19,7 @@ jobs: - name: Compile run: poetry run mypy . test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Checkout repo uses: actions/checkout@v3 @@ -39,7 +39,7 @@ jobs: publish: needs: [compile, test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Checkout repo uses: actions/checkout@v3 From b9e708df9ba2f6d64594e75110a2da98906bc2d1 Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 15:29:01 +0000 Subject: [PATCH 04/13] SDK regeneration --- .github/workflows/ci.yml | 4 +- .gitignore | 1 + .mock/definition/__package__.yml | 2894 +++++++++++ .mock/definition/accessGroups.yml | 80 + .mock/definition/api.yml | 13 + .mock/definition/assets.yml | 415 ++ .mock/definition/collections.yml | 186 + .mock/definition/collections/fields.yml | 189 + .mock/definition/collections/items.yml | 1628 ++++++ .mock/definition/components.yml | 486 ++ .mock/definition/ecommerce.yml | 42 + .mock/definition/forms.yml | 302 ++ .mock/definition/inventory.yml | 122 + .mock/definition/orders.yml | 1571 ++++++ .mock/definition/pages.yml | 470 ++ .mock/definition/pages/scripts.yml | 170 + .mock/definition/products.yml | 500 ++ .mock/definition/scripts.yml | 253 + .mock/definition/sites.yml | 495 ++ .mock/definition/sites/activityLogs.yml | 65 + .mock/definition/sites/plans.yml | 40 + .mock/definition/sites/redirects.yml | 190 + .mock/definition/sites/scripts.yml | 223 + .mock/definition/token.yml | 72 + .mock/definition/users.yml | 392 ++ .mock/definition/webhooks.yml | 189 + .mock/fern.config.json | 4 + poetry.lock | 340 +- pyproject.toml | 7 +- reference.md | 4410 ++++++++++++----- src/webflow/__init__.py | 105 +- src/webflow/client.py | 61 +- src/webflow/core/__init__.py | 25 +- src/webflow/core/client_wrapper.py | 19 +- src/webflow/core/file.py | 45 +- src/webflow/core/http_client.py | 80 +- src/webflow/core/jsonable_encoder.py | 64 +- src/webflow/core/pydantic_utilities.py | 276 +- src/webflow/core/query_encoder.py | 51 +- src/webflow/core/request_options.py | 3 + src/webflow/core/serialization.py | 272 + src/webflow/errors/bad_request_error.py | 5 +- src/webflow/errors/conflict_error.py | 5 +- src/webflow/errors/forbidden_error.py | 5 +- src/webflow/errors/internal_server_error.py | 5 +- src/webflow/errors/not_found_error.py | 5 +- src/webflow/errors/too_many_requests_error.py | 5 +- src/webflow/errors/unauthorized_error.py | 5 +- src/webflow/resources/__init__.py | 18 +- src/webflow/resources/access_groups/client.py | 197 +- .../types/access_groups_list_request_sort.py | 23 +- src/webflow/resources/assets/client.py | 1301 ++++- src/webflow/resources/collections/__init__.py | 22 +- src/webflow/resources/collections/client.py | 733 ++- .../collections/resources/__init__.py | 22 +- .../collections/resources/fields/client.py | 587 ++- .../fields/types/field_create_type.py | 84 +- .../collections/resources/items/__init__.py | 22 +- .../collections/resources/items/client.py | 3561 ++++++++++--- .../resources/items/types/__init__.py | 22 +- .../types/bulk_collection_item_field_data.py | 37 - ...collection_item_request_body_field_data.py | 9 + ...ction_item_request_body_field_data_item.py | 32 + .../types/items_create_item_live_request.py | 7 + .../items/types/items_create_item_request.py | 7 + ...ms_delete_items_live_request_items_item.py | 31 + .../items_delete_items_request_items_item.py | 31 + .../items_list_items_live_request_sort_by.py | 22 +- ...tems_list_items_live_request_sort_order.py | 14 +- .../types/items_list_items_request_sort_by.py | 22 +- .../items_list_items_request_sort_order.py | 14 +- .../types/items_publish_item_response.py | 24 + .../resources/items/types/multiple_items.py | 23 + .../items/types/multiple_live_items.py | 23 + .../resources/items/types/single_cms_item.py | 28 + src/webflow/resources/components/__init__.py | 15 + src/webflow/resources/components/client.py | 1476 ++++++ .../resources/components/types/__init__.py | 13 + .../types/component_dom_write_nodes_item.py | 7 + ...ponent_properties_write_properties_item.py | 34 + .../components_update_content_response.py | 22 + .../components_update_properties_response.py | 22 + src/webflow/resources/ecommerce/client.py | 205 +- src/webflow/resources/forms/client.py | 973 +++- src/webflow/resources/inventory/client.py | 417 +- ...inventory_update_request_inventory_type.py | 18 +- src/webflow/resources/orders/client.py | 1159 ++++- .../types/orders_list_request_status.py | 36 +- .../types/orders_refund_request_reason.py | 26 +- src/webflow/resources/pages/__init__.py | 4 +- src/webflow/resources/pages/client.py | 1142 ++++- .../pages/resources/scripts/client.py | 561 ++- src/webflow/resources/pages/types/__init__.py | 4 +- .../pages/types/dom_write_nodes_item.py | 39 - .../pages/types/page_dom_write_nodes_item.py | 7 + .../types/update_static_content_response.py | 34 +- src/webflow/resources/products/client.py | 1266 ++++- .../types/products_create_sku_response.py | 32 +- src/webflow/resources/scripts/client.py | 525 +- src/webflow/resources/sites/__init__.py | 5 +- src/webflow/resources/sites/client.py | 1392 +++++- .../resources/sites/resources/__init__.py | 4 +- .../sites/resources/activity_logs/client.py | 147 +- .../sites/resources/plans/__init__.py} | 3 - .../resources/sites/resources/plans/client.py | 233 + .../sites/resources/redirects/__init__.py | 2 + .../sites/resources/redirects/client.py | 989 ++++ .../sites/resources/scripts/client.py | 680 ++- src/webflow/resources/sites/types/__init__.py | 5 + .../sites/types/sites_publish_response.py | 34 + src/webflow/resources/token/client.py | 167 +- src/webflow/resources/users/client.py | 938 +++- .../users/types/users_list_request_sort.py | 103 +- .../users/types/users_update_request_data.py | 46 +- src/webflow/resources/webhooks/client.py | 743 ++- src/webflow/types/__init__.py | 87 +- src/webflow/types/access_group.py | 51 +- src/webflow/types/access_group_list.py | 48 +- src/webflow/types/application.py | 2 +- src/webflow/types/asset.py | 89 +- src/webflow/types/asset_folder.py | 63 +- src/webflow/types/asset_folder_list.py | 40 +- src/webflow/types/asset_upload.py | 69 +- .../types/asset_upload_upload_details.py | 50 +- src/webflow/types/asset_variant.py | 58 +- src/webflow/types/assets.py | 32 +- src/webflow/types/authorization.py | 36 +- .../types/authorization_authorization.py | 65 +- ...thorization_authorization_authorized_to.py | 48 +- src/webflow/types/authorized_user.py | 50 +- src/webflow/types/bad_request_error_body.py | 1 - src/webflow/types/bulk_collection_item.py | 75 + .../types/bulk_collection_item_field_data.py | 27 + src/webflow/types/collection.py | 59 +- src/webflow/types/collection_item.py | 70 +- .../types/collection_item_field_data.py | 36 +- src/webflow/types/collection_item_list.py | 34 +- .../collection_item_list_no_pagination.py | 27 + .../types/collection_item_list_pagination.py | 38 +- .../types/collection_item_patch_single.py | 75 + ...collection_item_patch_single_field_data.py | 27 + .../types/collection_item_post_single.py | 77 + .../collection_item_post_single_field_data.py | 27 + .../types/collection_item_with_id_input.py | 75 + ...ollection_item_with_id_input_field_data.py | 27 + src/webflow/types/collection_list.py | 34 +- .../types/collection_list_array_item.py | 57 +- src/webflow/types/component.py | 46 + src/webflow/types/component_dom.py | 35 + ..._instance_node_property_overrides_write.py | 39 + ...overrides_write_property_overrides_item.py | 32 + src/webflow/types/component_list.py | 26 + src/webflow/types/component_node.py | 43 + src/webflow/types/component_properties.py | 35 + src/webflow/types/component_property.py | 47 + src/webflow/types/component_property_type.py | 5 + src/webflow/types/conflict_error_body.py | 1 - src/webflow/types/custom_code_block.py | 59 +- src/webflow/types/custom_code_block_type.py | 18 +- .../types/custom_code_hosted_response.py | 64 +- .../types/custom_code_inline_response.py | 64 +- src/webflow/types/dom.py | 42 +- src/webflow/types/domain.py | 44 +- src/webflow/types/domains.py | 40 +- src/webflow/types/duplicate_user_email.py | 4 +- src/webflow/types/ecommerce_settings.py | 49 +- src/webflow/types/error.py | 48 +- src/webflow/types/error_code.py | 38 + src/webflow/types/field.py | 54 +- src/webflow/types/field_type.py | 83 +- src/webflow/types/forbidden_error_body.py | 34 +- src/webflow/types/form.py | 94 +- src/webflow/types/form_field.py | 1 - src/webflow/types/form_field_value.py | 48 +- src/webflow/types/form_field_value_type.py | 34 +- src/webflow/types/form_list.py | 32 +- src/webflow/types/form_response_settings.py | 52 +- src/webflow/types/form_submission.py | 65 +- src/webflow/types/form_submission_list.py | 38 +- src/webflow/types/image_node.py | 45 +- src/webflow/types/image_node_image.py | 22 + src/webflow/types/invalid_domain.py | 2 +- ...rror_details_item.py => invalid_scopes.py} | 2 +- src/webflow/types/inventory_item.py | 44 +- .../types/inventory_item_inventory_type.py | 18 +- src/webflow/types/list_custom_code_blocks.py | 32 +- src/webflow/types/locale.py | 58 +- src/webflow/types/locales.py | 36 +- src/webflow/types/no_domains.py | 2 +- src/webflow/types/node.py | 88 +- src/webflow/types/node_type.py | 17 - src/webflow/types/not_enterprise_plan_site.py | 4 +- .../types/not_enterprise_plan_workspace.py | 5 + src/webflow/types/oauth_scope.py | 172 - src/webflow/types/order.py | 185 +- src/webflow/types/order_address.py | 64 +- src/webflow/types/order_address_japan_type.py | 18 +- src/webflow/types/order_address_type.py | 18 +- src/webflow/types/order_customer_info.py | 42 +- .../types/order_dispute_last_status.py | 58 +- .../types/order_download_files_item.py | 38 +- src/webflow/types/order_list.py | 34 +- src/webflow/types/order_metadata.py | 38 +- src/webflow/types/order_price.py | 38 +- src/webflow/types/order_purchased_item.py | 86 +- .../order_purchased_item_variant_image.py | 34 +- ...order_purchased_item_variant_image_file.py | 57 +- ...d_item_variant_image_file_variants_item.py | 48 +- src/webflow/types/order_status.py | 40 +- src/webflow/types/order_totals.py | 38 +- src/webflow/types/order_totals_extras_item.py | 42 +- .../types/order_totals_extras_item_type.py | 30 +- src/webflow/types/page.py | 100 +- src/webflow/types/page_details.py | 115 - src/webflow/types/page_details_open_graph.py | 53 - src/webflow/types/page_details_seo.py | 41 - src/webflow/types/page_list.py | 32 +- src/webflow/types/page_open_graph.py | 48 +- src/webflow/types/page_seo.py | 36 +- src/webflow/types/pagination.py | 38 +- src/webflow/types/paypal_details.py | 60 +- src/webflow/types/product.py | 65 +- src/webflow/types/product_and_sk_us.py | 34 +- src/webflow/types/product_and_sk_us_list.py | 36 +- src/webflow/types/product_field_data.py | 72 +- .../product_field_data_ec_product_type.py | 38 +- .../types/product_field_data_tax_category.py | 163 +- src/webflow/types/publish_status.py | 18 +- src/webflow/types/redirect.py | 42 + src/webflow/types/redirects.py | 30 + src/webflow/types/registered_script_list.py | 42 +- src/webflow/types/script_apply.py | 44 +- src/webflow/types/script_apply_list.py | 46 +- src/webflow/types/script_apply_location.py | 18 +- src/webflow/types/scripts.py | 1 - src/webflow/types/site.py | 95 +- src/webflow/types/site_activity_log_item.py | 64 +- .../types/site_activity_log_item_event.py | 51 + ...te_activity_log_item_resource_operation.py | 43 +- .../types/site_activity_log_item_user.py | 38 +- .../types/site_activity_log_response.py | 34 +- .../types/site_data_collection_type.py | 5 + src/webflow/types/site_plan.py | 38 + src/webflow/types/site_plan_id.py | 21 + src/webflow/types/site_plan_name.py | 15 + src/webflow/types/sites.py | 32 +- src/webflow/types/sku.py | 57 +- src/webflow/types/sku_field_data.py | 70 +- .../types/sku_field_data_compare_at_price.py | 36 +- .../sku_field_data_ec_sku_billing_method.py | 14 +- ...sku_field_data_ec_sku_subscription_plan.py | 38 +- ..._data_ec_sku_subscription_plan_interval.py | 30 +- ...ata_ec_sku_subscription_plan_plans_item.py | 38 +- ...sku_subscription_plan_plans_item_status.py | 28 +- src/webflow/types/sku_field_data_price.py | 36 +- src/webflow/types/sku_property_list.py | 38 +- .../types/sku_property_list_enum_item.py | 38 +- src/webflow/types/stripe_card.py | 48 +- src/webflow/types/stripe_card_brand.py | 44 +- src/webflow/types/stripe_card_expires.py | 36 +- src/webflow/types/stripe_details.py | 68 +- src/webflow/types/text.py | 27 + src/webflow/types/text_node.py | 45 +- src/webflow/types/text_node_text.py | 27 + src/webflow/types/text_node_write.py | 33 + src/webflow/types/trigger_type.py | 107 +- src/webflow/types/user.py | 69 +- src/webflow/types/user_access_groups_item.py | 41 +- .../types/user_access_groups_item_type.py | 21 +- src/webflow/types/user_data.py | 32 +- src/webflow/types/user_data_data.py | 52 +- src/webflow/types/user_limit_reached.py | 4 +- src/webflow/types/user_list.py | 42 +- src/webflow/types/user_status.py | 26 +- src/webflow/types/users_not_enabled.py | 4 +- src/webflow/types/webhook.py | 72 +- src/webflow/types/webhook_filter.py | 26 + src/webflow/types/webhook_list.py | 32 +- src/webflow/version.py | 1 - tests/__init__.py | 2 + tests/collections/__init__.py | 2 + tests/collections/test_fields.py | 97 + tests/collections/test_items.py | 810 +++ tests/conftest.py | 20 + tests/custom/test_client.py | 1 + tests/pages/__init__.py | 2 + tests/pages/test_scripts.py | 85 + tests/sites/__init__.py | 2 + tests/sites/test_activity_logs.py | 53 + tests/sites/test_plans.py | 20 + tests/sites/test_redirects.py | 88 + tests/sites/test_scripts.py | 154 + tests/test_access_groups.py | 49 + tests/test_assets.py | 358 ++ tests/test_collections.py | 188 + tests/test_components.py | 266 + tests/test_ecommerce.py | 20 + tests/test_forms.py | 266 + tests/test_inventory.py | 32 + tests/test_orders.py | 2327 +++++++++ tests/test_pages.py | 403 ++ tests/test_products.py | 465 ++ tests/test_scripts.py | 157 + tests/test_sites.py | 637 +++ tests/test_token.py | 66 + tests/test_users.py | 301 ++ tests/test_webhooks.py | 175 + tests/utilities.py | 162 + tests/utils/__init__.py | 2 + tests/utils/assets/models/__init__.py | 21 + tests/utils/assets/models/circle.py | 11 + tests/utils/assets/models/color.py | 7 + .../assets/models/object_with_defaults.py | 16 + .../models/object_with_optional_field.py | 34 + tests/utils/assets/models/shape.py | 26 + tests/utils/assets/models/square.py | 11 + .../assets/models/undiscriminated_shape.py | 9 + tests/utils/test_http_client.py | 14 + tests/utils/test_query_encoding.py | 40 +- tests/utils/test_serialization.py | 72 + 320 files changed, 43466 insertions(+), 8449 deletions(-) create mode 100644 .mock/definition/__package__.yml create mode 100644 .mock/definition/accessGroups.yml create mode 100644 .mock/definition/api.yml create mode 100644 .mock/definition/assets.yml create mode 100644 .mock/definition/collections.yml create mode 100644 .mock/definition/collections/fields.yml create mode 100644 .mock/definition/collections/items.yml create mode 100644 .mock/definition/components.yml create mode 100644 .mock/definition/ecommerce.yml create mode 100644 .mock/definition/forms.yml create mode 100644 .mock/definition/inventory.yml create mode 100644 .mock/definition/orders.yml create mode 100644 .mock/definition/pages.yml create mode 100644 .mock/definition/pages/scripts.yml create mode 100644 .mock/definition/products.yml create mode 100644 .mock/definition/scripts.yml create mode 100644 .mock/definition/sites.yml create mode 100644 .mock/definition/sites/activityLogs.yml create mode 100644 .mock/definition/sites/plans.yml create mode 100644 .mock/definition/sites/redirects.yml create mode 100644 .mock/definition/sites/scripts.yml create mode 100644 .mock/definition/token.yml create mode 100644 .mock/definition/users.yml create mode 100644 .mock/definition/webhooks.yml create mode 100644 .mock/fern.config.json create mode 100644 src/webflow/core/serialization.py delete mode 100644 src/webflow/resources/collections/resources/items/types/bulk_collection_item_field_data.py create mode 100644 src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data.py create mode 100644 src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data_item.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_create_item_live_request.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_create_item_request.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_delete_items_request_items_item.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_publish_item_response.py create mode 100644 src/webflow/resources/collections/resources/items/types/multiple_items.py create mode 100644 src/webflow/resources/collections/resources/items/types/multiple_live_items.py create mode 100644 src/webflow/resources/collections/resources/items/types/single_cms_item.py create mode 100644 src/webflow/resources/components/__init__.py create mode 100644 src/webflow/resources/components/client.py create mode 100644 src/webflow/resources/components/types/__init__.py create mode 100644 src/webflow/resources/components/types/component_dom_write_nodes_item.py create mode 100644 src/webflow/resources/components/types/component_properties_write_properties_item.py create mode 100644 src/webflow/resources/components/types/components_update_content_response.py create mode 100644 src/webflow/resources/components/types/components_update_properties_response.py delete mode 100644 src/webflow/resources/pages/types/dom_write_nodes_item.py create mode 100644 src/webflow/resources/pages/types/page_dom_write_nodes_item.py rename src/webflow/{types/missing_scopes.py => resources/sites/resources/plans/__init__.py} (57%) create mode 100644 src/webflow/resources/sites/resources/plans/client.py create mode 100644 src/webflow/resources/sites/resources/redirects/__init__.py create mode 100644 src/webflow/resources/sites/resources/redirects/client.py create mode 100644 src/webflow/resources/sites/types/__init__.py create mode 100644 src/webflow/resources/sites/types/sites_publish_response.py create mode 100644 src/webflow/types/bulk_collection_item.py create mode 100644 src/webflow/types/bulk_collection_item_field_data.py create mode 100644 src/webflow/types/collection_item_list_no_pagination.py create mode 100644 src/webflow/types/collection_item_patch_single.py create mode 100644 src/webflow/types/collection_item_patch_single_field_data.py create mode 100644 src/webflow/types/collection_item_post_single.py create mode 100644 src/webflow/types/collection_item_post_single_field_data.py create mode 100644 src/webflow/types/collection_item_with_id_input.py create mode 100644 src/webflow/types/collection_item_with_id_input_field_data.py create mode 100644 src/webflow/types/component.py create mode 100644 src/webflow/types/component_dom.py create mode 100644 src/webflow/types/component_instance_node_property_overrides_write.py create mode 100644 src/webflow/types/component_instance_node_property_overrides_write_property_overrides_item.py create mode 100644 src/webflow/types/component_list.py create mode 100644 src/webflow/types/component_node.py create mode 100644 src/webflow/types/component_properties.py create mode 100644 src/webflow/types/component_property.py create mode 100644 src/webflow/types/component_property_type.py create mode 100644 src/webflow/types/error_code.py create mode 100644 src/webflow/types/image_node_image.py rename src/webflow/types/{error_details_item.py => invalid_scopes.py} (54%) delete mode 100644 src/webflow/types/node_type.py create mode 100644 src/webflow/types/not_enterprise_plan_workspace.py delete mode 100644 src/webflow/types/oauth_scope.py delete mode 100644 src/webflow/types/page_details.py delete mode 100644 src/webflow/types/page_details_open_graph.py delete mode 100644 src/webflow/types/page_details_seo.py create mode 100644 src/webflow/types/redirect.py create mode 100644 src/webflow/types/redirects.py create mode 100644 src/webflow/types/site_activity_log_item_event.py create mode 100644 src/webflow/types/site_data_collection_type.py create mode 100644 src/webflow/types/site_plan.py create mode 100644 src/webflow/types/site_plan_id.py create mode 100644 src/webflow/types/site_plan_name.py create mode 100644 src/webflow/types/text.py create mode 100644 src/webflow/types/text_node_text.py create mode 100644 src/webflow/types/text_node_write.py create mode 100644 src/webflow/types/webhook_filter.py create mode 100644 tests/__init__.py create mode 100644 tests/collections/__init__.py create mode 100644 tests/collections/test_fields.py create mode 100644 tests/collections/test_items.py create mode 100644 tests/conftest.py create mode 100644 tests/pages/__init__.py create mode 100644 tests/pages/test_scripts.py create mode 100644 tests/sites/__init__.py create mode 100644 tests/sites/test_activity_logs.py create mode 100644 tests/sites/test_plans.py create mode 100644 tests/sites/test_redirects.py create mode 100644 tests/sites/test_scripts.py create mode 100644 tests/test_access_groups.py create mode 100644 tests/test_assets.py create mode 100644 tests/test_collections.py create mode 100644 tests/test_components.py create mode 100644 tests/test_ecommerce.py create mode 100644 tests/test_forms.py create mode 100644 tests/test_inventory.py create mode 100644 tests/test_orders.py create mode 100644 tests/test_pages.py create mode 100644 tests/test_products.py create mode 100644 tests/test_scripts.py create mode 100644 tests/test_sites.py create mode 100644 tests/test_token.py create mode 100644 tests/test_users.py create mode 100644 tests/test_webhooks.py create mode 100644 tests/utilities.py create mode 100644 tests/utils/__init__.py create mode 100644 tests/utils/assets/models/__init__.py create mode 100644 tests/utils/assets/models/circle.py create mode 100644 tests/utils/assets/models/color.py create mode 100644 tests/utils/assets/models/object_with_defaults.py create mode 100644 tests/utils/assets/models/object_with_optional_field.py create mode 100644 tests/utils/assets/models/shape.py create mode 100644 tests/utils/assets/models/square.py create mode 100644 tests/utils/assets/models/undiscriminated_shape.py create mode 100644 tests/utils/test_serialization.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c312a8..0cbadd0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,8 +33,10 @@ jobs: - name: Install dependencies run: poetry install + - name: Install Fern + run: npm install -g fern-api - name: Test - run: poetry run pytest ./tests/custom/ + run: fern test --command "poetry run pytest -rP ." publish: needs: [compile, test] diff --git a/.gitignore b/.gitignore index 42cb863..0da665f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ dist/ .mypy_cache/ __pycache__/ poetry.toml +.ruff_cache/ diff --git a/.mock/definition/__package__.yml b/.mock/definition/__package__.yml new file mode 100644 index 0000000..db84636 --- /dev/null +++ b/.mock/definition/__package__.yml @@ -0,0 +1,2894 @@ +errors: + UnauthorizedError: + status-code: 401 + type: Error + docs: >- + Provided access token is invalid or does not have access to requested + resource + examples: + - value: + code: not_authorized + message: Request not authorized + ForbiddenError: + status-code: 403 + type: unknown + docs: Provided access token is valid, but is missing the required scopes. + examples: + - value: + code: missing_scopes + message: >- + OAuthForbidden: You are missing the following scopes - + components:write + - value: + key: value + - value: + code: forbidden + message: User is not authorized to perform this action + BadRequestError: + status-code: 400 + type: unknown + docs: Request body was incorrectly formatted. + examples: + - value: + code: bad_request + message: 'Bad Request: Request is malformed' + - value: + key: value + - value: + code: validation_error + message: 'Validation Error: Provided ID is invalid' + NotFoundError: + status-code: 404 + type: Error + docs: Requested resource not found + examples: + - value: + code: resource_not_found + message: 'Requested resource not found: The site cannot be found' + TooManyRequestsError: + status-code: 429 + type: Error + docs: >- + The rate limit of the provided access_token has been reached. Please have + your application respect the X-RateLimit-Remaining header we include on + API responses. + examples: + - value: + code: too_many_requests + message: Too many requests + InternalServerError: + status-code: 500 + type: Error + docs: We had a problem with our server. Try again later. + examples: + - value: + code: internal_error + message: An Internal Error occurred + ConflictError: + status-code: 409 + type: unknown + docs: Site is published to multiple domains at different times + examples: + - value: + message: '''Site is published to multiple domains at different times' + - value: + code: custom_code_max_registered_scripts + message: The maximum number of registered scripts has been reached. + - value: + code: forms_require_republish + message: To access this feature, the site needs to be republished. + - value: + key: value + - value: + code: ecommerce_not_enabled + message: Ecommerce is not yet initialized +types: + ForbiddenErrorBody: + discriminated: false + union: + - InvalidScopes + - UsersNotEnabled + source: + openapi: ../../../openapi/referenced-specs/v2.yml + BadRequestErrorBody: + discriminated: false + union: + - InvalidDomain + - NoDomains + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ConflictErrorBody: + discriminated: false + union: + - DuplicateUserEmail + - UserLimitReached + source: + openapi: ../../../openapi/referenced-specs/v2.yml + AuthorizedUser: + properties: + id: + type: optional + docs: The unique ID of the user + email: + type: optional + docs: The user's email address + validation: + format: email + firstName: + type: optional + docs: The user's first name + lastName: + type: optional + docs: The user's last name + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ErrorCode: + enum: + - bad_request + - collection_not_found + - conflict + - duplicate_collection + - duplicate_user_email + - ecommerce_not_enabled + - forbidden + - forms_require_republish + - incompatible_webhook_filter + - internal_error + - invalid_auth_version + - invalid_credentials + - invalid_domain + - invalid_user_email + - item_not_found + - missing_scopes + - no_domains + - not_authorized + - not_enterprise_plan_site + - not_enterprise_plan_workspace + - order_not_found + - resource_not_found + - too_many_requests + - unsupported_version + - unsupported_webhook_trigger_type + - user_limit_reached + - user_not_found + - users_not_enabled + - validation_error + docs: Error code + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Error: + properties: + code: + type: optional + docs: Error code + message: + type: optional + docs: Error message + externalReference: + type: optional + docs: Link to more information + details: + type: optional> + docs: Array of errors + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Application: unknown + AuthorizationAuthorizationAuthorizedTo: + properties: + siteIds: + type: optional> + docs: Array of Sites this app is authorized to + workspaceIds: + type: optional> + docs: Array of Workspaces this app is authorized to + userIds: + type: optional> + docs: Array of Users this app is authorized to + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + AuthorizationAuthorization: + docs: The Authorization object + properties: + id: + type: optional + docs: The unique ID of the Authorization instance + createdOn: + type: optional + docs: The date the Authorization was created + lastUsed: + type: optional + docs: The date the Authorization was last used + grantType: + type: optional + docs: The grant type of the Authorization + rateLimit: + type: optional + docs: The default rate limit for the Authorization (requests/min) + scope: + type: optional + docs: Comma separted list of OAuth scopes corresponding to the Authorization + authorizedTo: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Authorization: + properties: + authorization: + type: optional + docs: The Authorization object + application: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Domain: + properties: + id: + type: string + docs: Unique identifier for the Domain + url: + type: optional + docs: The registered Domain name + lastPublished: + type: optional + docs: The date the custom domain was last published to + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Locale: + properties: + id: + type: optional + docs: The unique identifier for the locale. + cmsLocaleId: + type: optional + docs: A CMS-specific identifier for the locale. + enabled: + type: optional + docs: Indicates if the locale is enabled. + displayName: + type: optional + docs: The display name of the locale, typically in English. + displayImageId: + type: optional + docs: An optional ID for an image associated with the locale, nullable. + redirect: + type: optional + docs: Determines if requests should redirect to the locale's subdirectory. + subdirectory: + type: optional + docs: The subdirectory path for the locale, used in URLs. + tag: + type: optional + docs: >- + A tag or code representing the locale, often following a standard + format like 'en-US'. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Locales: + properties: + primary: + type: optional + docs: The primary locale for the site or application. + secondary: + type: optional> + docs: A list of secondary locales available for the site or application. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SiteDataCollectionType: + enum: + - always + - optOut + - disabled + docs: The type of data collection enabled for the site. + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Site: + properties: + id: + type: string + docs: Unique identifier for the Site + workspaceId: + type: optional + docs: Unique identifier for the Workspace + createdOn: + type: optional + docs: Date the Site was created + displayName: + type: optional + docs: Name given to Site + shortName: + type: optional + docs: Slugified version of name + lastPublished: + type: optional + docs: Date the Site was last published + lastUpdated: + type: optional + docs: Date the Site was last updated + previewUrl: + type: optional + docs: URL of a generated image for the given Site + validation: + format: uri + timeZone: + type: optional + docs: Site timezone set under Site Settings + parentFolderId: + type: optional + docs: The ID of the parent folder the Site exists in + customDomains: optional> + locales: optional + dataCollectionEnabled: + type: optional + docs: Indicates if data collection is enabled for the site. + dataCollectionType: + type: optional + docs: The type of data collection enabled for the site. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + InvalidScopes: unknown + NotEnterprisePlanWorkspace: unknown + Sites: + properties: + sites: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + NotEnterprisePlanSite: unknown + Domains: + properties: + customDomains: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + InvalidDomain: unknown + NoDomains: unknown + Redirect: + docs: A single redirection rule, specifying a source URL and a destination URL. + properties: + id: + type: optional + docs: The ID of the specific redirect rule + fromUrl: + type: optional + docs: The source URL path that will be redirected. + toUrl: + type: optional + docs: The target URL path where the user or client will be redirected. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Pagination: + docs: Pagination object + properties: + limit: + type: optional + docs: The limit used for pagination + offset: + type: optional + docs: The offset used for pagination + total: + type: optional + docs: The total number of records + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Redirects: + docs: Site redirects response + properties: + redirects: + type: optional> + docs: List of redirects for a given site + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SitePlanId: + enum: + - value: hosting-basic-v3 + name: HostingBasicV3 + - value: hosting-cms-v3 + name: HostingCmsV3 + - value: hosting-business-v3 + name: HostingBusinessV3 + - value: hosting-ecommerce-standard-v2 + name: HostingEcommerceStandardV2 + - value: hosting-ecommerce-plus-v2 + name: HostingEcommercePlusV2 + - value: hosting-ecommerce-advanced-v2 + name: HostingEcommerceAdvancedV2 + - value: hosting-basic-v4 + name: HostingBasicV4 + - value: hosting-cms-v4 + name: HostingCmsV4 + - value: hosting-business-v4 + name: HostingBusinessV4 + - value: hosting-ecommerce-standard-v3 + name: HostingEcommerceStandardV3 + - value: hosting-ecommerce-plus-v3 + name: HostingEcommercePlusV3 + - value: hosting-ecommerce-advanced-v3 + name: HostingEcommerceAdvancedV3 + docs: ID of the hosting plan. + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SitePlanName: + enum: + - value: Basic Hosting + name: BasicHosting + - value: CMS Hosting + name: CmsHosting + - value: Business Hosting + name: BusinessHosting + - value: ECommerce Standard Hosting + name: ECommerceStandardHosting + - value: ECommerce Plus Hosting + name: ECommercePlusHosting + - value: ECommerce Advanced Hosting + name: ECommerceAdvancedHosting + docs: Name of the hosting plan. + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SitePlan: + properties: + id: + type: optional + docs: ID of the hosting plan. + name: + type: optional + docs: Name of the hosting plan. + pricingInfo: + type: optional + docs: URL for more information about Webflow hosting plan pricing. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SiteActivityLogItemEvent: + enum: + - styles_modified + - site_published + - ix2_modified_on_page + - page_dom_modified + - cms_item + - backup_created + - page_custom_code_modified + - symbols_modified + - variable_modified + - variables_modified + - cms_collection + - page_settings_modified + - page_settings_custom_code_modified + - ix2_modified_on_component + - ix2_modified_on_class + - site_custom_code_modified + - page_duplicated + - secondary_locale_page_content_modified + - page_renamed + - page_created + - page_deleted + - site_unpublished + - backup_restored + - locale_added + - branch_created + - locale_display_name_updated + - locale_subdirectory_updated + - branch_merged + - locale_tag_updated + - branch_deleted + - locale_enabled + - locale_removed + - locale_disabled + - library_shared + - library_unshared + - library_installed + - library_uninstalled + - library_update_shared + - library_update_accepted + - branch_review_created + - branch_review_approved + - branch_review_canceled + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SiteActivityLogItemResourceOperation: + enum: + - CREATED + - MODIFIED + - PUBLISHED + - UNPUBLISHED + - DELETED + - GROUP_REORDERED + - GROUP_CREATED + - GROUP_DELETED + - REORDERED + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SiteActivityLogItemUser: + properties: + id: optional + displayName: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + SiteActivityLogItem: + properties: + id: optional + createdOn: optional + lastUpdated: optional + event: optional + resourceOperation: optional + user: optional + resourceId: optional + resourceName: optional + newValue: optional + previousValue: optional + payload: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SiteActivityLogResponse: + properties: + items: optional> + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionListArrayItem: + docs: A collection object + properties: + id: + type: string + docs: Unique identifier for a Collection + displayName: + type: optional + docs: Name given to the Collection + singularName: + type: optional + docs: >- + The name of one Item in Collection (e.g. ”Blog Post” if the Collection + is called “Blog Posts”) + slug: + type: optional + docs: Slug of Collection in Site URL structure + createdOn: + type: optional + docs: The date the collection was created + lastUpdated: + type: optional + docs: The date the collection was last updated + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionList: + properties: + collections: + type: optional> + docs: An array of Collections + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FieldType: + enum: + - Color + - DateTime + - Email + - ExtFileRef + - Image + - Link + - MultiImage + - Number + - Phone + - PlainText + - RichText + - Switch + - Video + docs: Choose these appropriate field type for your collection data + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Field: + docs: The details of a field in a collection + properties: + id: + type: string + docs: Unique identifier for a Field + isRequired: + type: boolean + docs: define whether a field is required in a collection + isEditable: + type: optional + docs: Define whether the field is editable + type: + type: FieldType + docs: Choose these appropriate field type for your collection data + slug: + type: optional + docs: >- + Slug of Field in Site URL structure. Slugs should be all lowercase + with no spaces. Any spaces will be converted to "-." + displayName: + type: string + docs: The name of a field + helpText: + type: optional + docs: Additional text to help anyone filling out this field + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Collection: + docs: A collection object + properties: + id: + type: string + docs: Unique identifier for a Collection + displayName: + type: optional + docs: Name given to the Collection + singularName: + type: optional + docs: >- + The name of one Item in Collection (e.g. ”Blog Post” if the Collection + is called “Blog Posts”) + slug: + type: optional + docs: Slug of Collection in Site URL structure + createdOn: + type: optional + docs: The date the collection was created + lastUpdated: + type: optional + docs: The date the collection was last updated + fields: + docs: The list of fields in the Collection + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemFieldData: + properties: + name: + type: string + docs: Name of the Item + slug: + type: string + docs: >- + URL structure of the Item in your site. Note: Updates to an item slug + will break all links referencing the old slug. + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItem: + docs: > + A Collection Item represents a single entry in your collection. Each item + includes: + + + - **System metadata** - Automatically managed fields like IDs and + timestamp
+ + - **Status flags** - Controls for managing content state: `isDraft`, + `isArchived `
+ + - **Content fields** - Stored in `fieldData`. Each item needs a `name` and + `slug`, and may include additional fields matching your collection's + schema definition. + properties: + id: + type: optional + docs: Unique identifier for the Item + cmsLocaleId: + type: optional + docs: Identifier for the locale of the CMS item + lastPublished: + type: optional + docs: The date the item was last published + lastUpdated: + type: optional + docs: The date the item was last updated + createdOn: + type: optional + docs: The date the item was created + isArchived: + type: optional + docs: Boolean determining if the Item is set to archived + default: false + isDraft: + type: optional + docs: Boolean determining if the Item is set to draft + default: false + fieldData: CollectionItemFieldData + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemListPagination: + properties: + limit: + type: optional + docs: The limit specified in the request + default: 100 + offset: + type: optional + docs: The offset specified for pagination + default: 0 + total: + type: optional + docs: Total number of items in the collection + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemList: + docs: Results from collection items list + properties: + items: + type: optional> + docs: List of Items within the collection + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemPostSingleFieldData: + properties: + name: + type: string + docs: Name of the Item + slug: + type: string + docs: >- + URL structure of the Item in your site. Note: Updates to an item slug + will break all links referencing the old slug. + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemPostSingle: + docs: > + A Collection Item represents a single entry in your collection. Each item + includes: + + + - **System metadata** - Automatically managed fields like IDs and + timestamp
+ + - **Status flags** - Controls for managing content state: `isDraft`, + `isArchived `
+ + - **Content fields** - Stored in `fieldData`. Each item needs a `name` and + `slug`, and may include additional fields matching your collection's + schema definition. + properties: + id: + type: optional + docs: Unique identifier for the Item + cmsLocaleId: + type: optional + docs: Identifier for the locale of the CMS item + lastPublished: + type: optional + docs: The date the item was last published + lastUpdated: + type: optional + docs: The date the item was last updated + createdOn: + type: optional + docs: The date the item was created + isArchived: + type: optional + docs: Boolean determining if the Item is in an archived state. + default: false + isDraft: + type: optional + docs: Boolean determining if the Item is in a draft state. + default: false + fieldData: CollectionItemPostSingleFieldData + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemWithIdInputFieldData: + properties: + name: + type: optional + docs: Name of the Item + slug: + type: optional + docs: >- + URL structure of the Item in your site. Note: Updates to an item slug + will break all links referencing the old slug. + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemWithIdInput: + docs: > + The fields that define the schema for a given Item are based on the + Collection that Item belongs to. Beyond the user defined fields, there are + a handful of additional fields that are automatically created for all + items + properties: + id: + type: string + docs: Unique identifier for the Item + cmsLocaleId: + type: optional + docs: Identifier for the locale of the CMS item + lastPublished: + type: optional + docs: The date the item was last published + lastUpdated: + type: optional + docs: The date the item was last updated + createdOn: + type: optional + docs: The date the item was created + isArchived: + type: optional + docs: Boolean determining if the Item is set to archived + isDraft: + type: optional + docs: Boolean determining if the Item is set to draft + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemListNoPagination: + docs: Results from collection items list + properties: + items: + type: optional> + docs: List of Items within the collection + source: + openapi: ../../../openapi/referenced-specs/v2.yml + BulkCollectionItemFieldData: + properties: + name: + type: optional + docs: Name of the Item + slug: + type: optional + docs: >- + URL structure of the Item in your site. Note: Updates to an item slug + will break all links referencing the old slug. + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + BulkCollectionItem: + docs: > + The fields that define the schema for a given Item are based on the + Collection that Item belongs to. Beyond the user defined fields, there are + a handful of additional fields that are automatically created for all + items + properties: + id: + type: string + docs: Unique identifier for the Item + cmsLocaleIds: + type: optional> + docs: Array of identifiers for the locales where the item will be created + lastPublished: + type: optional + docs: The date the item was last published + lastUpdated: + type: optional + docs: The date the item was last updated + createdOn: + type: optional + docs: The date the item was created + isArchived: + type: optional + docs: Boolean determining if the Item is set to archived + default: false + isDraft: + type: optional + docs: Boolean determining if the Item is set to draft + default: false + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemPatchSingleFieldData: + properties: + name: + type: optional + docs: Name of the Item + slug: + type: optional + docs: >- + URL structure of the Item in your site. Note: Updates to an item slug + will break all links referencing the old slug. + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemPatchSingle: + docs: > + The fields that define the schema for a given Item are based on the + Collection that Item belongs to. Beyond the user defined fields, there are + a handful of additional fields that are automatically created for all + items + properties: + id: + type: optional + docs: Unique identifier for the Item + cmsLocaleId: + type: optional + docs: Identifier for the locale of the CMS item + lastPublished: + type: optional + docs: The date the item was last published + lastUpdated: + type: optional + docs: The date the item was last updated + createdOn: + type: optional + docs: The date the item was created + isArchived: + type: optional + docs: Boolean determining if the Item is set to archived + isDraft: + type: optional + docs: Boolean determining if the Item is set to draft + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PageSeo: + docs: SEO-related fields for the Page + properties: + title: + type: optional + docs: The Page title shown in search engine results + description: + type: optional + docs: The Page description shown in search engine results + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + PageOpenGraph: + docs: Open Graph fields for the Page + properties: + title: + type: optional + docs: The title supplied to Open Graph annotations + titleCopied: + type: optional + docs: Indicates the Open Graph title was copied from the SEO title + default: true + description: + type: optional + docs: The description supplied to Open Graph annotations + descriptionCopied: + type: optional + docs: >- + Indicates the Open Graph description was copied from the SEO + description + default: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Page: + docs: The Page object + properties: + id: + type: string + docs: Unique identifier for the Page + siteId: + type: optional + docs: Unique identifier for the Site + title: + type: optional + docs: Title of the Page + slug: + type: optional + docs: slug of the Page (derived from title) + parentId: + type: optional + docs: Identifier of the parent folder + collectionId: + type: optional + docs: >- + Unique identifier for a linked Collection, value will be null if the + Page is not part of a Collection. + createdOn: + type: optional + docs: The date the Page was created + lastUpdated: + type: optional + docs: The date the Page was most recently updated + archived: + type: optional + docs: Whether the Page has been archived + default: false + draft: + type: optional + docs: Whether the Page is a draft + default: false + canBranch: + type: optional + docs: >- + Indicates whether the Page supports [Page + Branching](https://university.webflow.com/lesson/page-branching) + default: false + isBranch: + type: optional + docs: >- + Indicates whether the Page is a Branch of another Page [Page + Branching](https://university.webflow.com/lesson/page-branching) + default: false + isMembersOnly: + type: optional + docs: >- + Indicates whether the Page is restricted by [Memberships + Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) + default: false + seo: + type: optional + docs: SEO-related fields for the Page + openGraph: + type: optional + docs: Open Graph fields for the Page + localeId: + type: optional + docs: Unique ID of the page locale + publishedPath: + type: optional + docs: Relative path of the published page URL + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PageList: + docs: The Page object + properties: + pages: optional> + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + TextNodeText: + properties: + html: + type: optional + docs: The HTML content of the text node. + text: + type: optional + docs: The raw text content of the text node. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + TextNode: + docs: > + Represents text content within the DOM. It contains both the raw text and + its HTML representation. Additional attributes can be associated with the + text for styling or other purposes. + properties: + id: + type: optional + docs: Node UUID + text: optional + attributes: + type: optional> + docs: The custom attributes of the node + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ImageNodeImage: + properties: + alt: optional + assetId: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ImageNode: + docs: > + Represents an image within the DOM. It contains details about the image, + such as its alternative text (alt) for accessibility and an asset + identifier for fetching the actual image resource. Additional attributes + can be associated with the image for styling or other purposes. + properties: + id: + type: optional + docs: Node UUID + image: optional + attributes: + type: optional> + docs: The custom attributes of the node + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Text: + properties: + html: + type: optional + docs: The HTML content of the text node. + text: + type: optional + docs: The raw text content of the text node. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ComponentPropertyType: + enum: + - value: Plain Text + name: PlainText + - value: Rich Text + name: RichText + - value: Alt Text + name: AltText + docs: The type of the property. + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ComponentProperty: + docs: > + Represents a property of a component instance in the DOM. A property + contains a list of both the raw text and the HTML representation, allowing + for flexibility in rendering and processing. Additional attributes can be + associated with the text for styling or other purposes. + properties: + propertyId: + type: optional + docs: The ID of the property. + type: + type: optional + docs: The type of the property. + label: + type: optional + docs: The label of the property in the UI. + text: + type: optional + docs: >- + Represents text content within the DOM. It contains both the raw text + and its HTML representation. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ComponentNode: + docs: > + Represents a component instance within the DOM. It contains details about + the component instance, such as its type and properties. + properties: + id: + type: optional + docs: Node UUID + componentId: + type: optional + docs: Component ID + propertyOverrides: + type: optional> + docs: List of component properties with overrides for a component instance. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Node: + discriminant: type + base-properties: {} + docs: > + A generic representation of a content element within the Document Object + Model (DOM). Each node has a unique identifier and a specific type that + determines its content structure and attributes. + union: + text: TextNode + image: ImageNode + component-instance: ComponentNode + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Dom: + docs: > + The DOM (Document Object Model) schema represents the content structure of + a web page or component. It captures various content nodes along with + their associated attributes. Each node has a unique identifier and can be + of different types like text, image or component-instance. The schema also + provides pagination details for scenarios where the content nodes are too + many to be fetched in a single request. + properties: + pageId: + type: optional + docs: Page ID + nodes: optional> + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + TextNodeWrite: + docs: Update a text node + properties: + nodeId: + type: string + docs: Node UUID + text: + type: string + docs: >- + HTML content of the node, including the HTML tag. The HTML tags must + be the same as what's returned from the Get Content endpoint. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem: + properties: + propertyId: + type: string + docs: The ID of the property. + text: + type: string + docs: > + The new string or HTML value used to override the component instance + property value. + + The provided value must be compatible with the type of the component + instance property. + + For example, attempting to override a single-line plain-text property + with a multi-line + + value will result in an error. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ComponentInstanceNodePropertyOverridesWrite: + docs: Update text property overrides of a component instance + properties: + nodeId: + type: string + docs: Node UUID + propertyOverrides: + docs: >- + A list of component instance properties to override within the + specified secondary locale. + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Component: + docs: The Component object + properties: + id: + type: string + docs: Unique identifier for the Component + name: + type: optional + docs: Component Name + group: + type: optional + docs: The group that the component belongs to + description: + type: optional + docs: Component Description + readonly: + type: optional + docs: >- + Indicates whether the component is read-only. Components that cannot + be updated within this Site are set to readonly. Workspace Libraries + are a good example. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ComponentList: + docs: List of Components on a site. + properties: + components: optional> + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ComponentDom: + docs: > + The Component DOM schema represents the content structure of a component. + Similar to Page DOM, it captures various content nodes and their + associated attributes, but specifically for a component's structure. Each + node has a unique identifier and can contain text, images, or nested + component instances. + properties: + componentId: + type: optional + docs: Component ID + nodes: optional> + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ComponentProperties: + docs: > + The Component Properties schema represents a list of properties that store + text content. Each property has a unique identifier and can be of + different types like plain text or rich text. The schema also provides + pagination details for scenarios where there more properties than the + limit. + properties: + componentId: + type: optional + docs: Component ID + properties: optional> + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ScriptApplyLocation: + enum: + - header + - footer + docs: >- + Location of the script, either in the header or footer of the published + site + default: header + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ScriptApply: + properties: + id: + type: string + docs: ID of the registered custom code script + location: + type: ScriptApplyLocation + docs: >- + Location of the script, either in the header or footer of the + published site + default: header + version: + type: string + docs: Semantic Version String for the registered script *e.g. 0.0.1* + attributes: + type: optional> + docs: >- + Developer-specified key/value pairs to be applied as attributes to the + script + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ScriptApplyList: + properties: + scripts: + type: optional> + docs: A list of scripts applied to a Site or a Page + lastUpdated: + type: optional + docs: Date when the Site's scripts were last updated + createdOn: + type: optional + docs: Date when the Site's scripts were created + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CustomCodeHostedResponse: + docs: Registered custom code for application + properties: + id: + type: optional + docs: Human readable id, derived from the user-specified display name + canCopy: + type: optional + docs: >- + Define whether the script can be copied on site duplication and + transfer + default: false + displayName: + type: optional + docs: >- + User-facing name for the script. Must be between 1 and 50 alphanumeric + characters + hostedLocation: + type: optional + docs: URI for an externally hosted script location + integrityHash: + type: optional + docs: >- + Sub-Resource Integrity Hash. Only required for externally hosted + scripts (passed via hostedLocation) + createdOn: + type: optional + docs: Timestamp when the script version was created + lastUpdated: + type: optional + docs: Timestamp when the script version was last updated + version: + type: optional + docs: A Semantic Version (SemVer) string, denoting the version of the script + source: + openapi: ../../../openapi/referenced-specs/v2.yml + RegisteredScriptList: + docs: A list of scripts registered to the site + properties: + registeredScripts: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CustomCodeInlineResponse: + docs: Registered custom code for application + properties: + id: + type: optional + docs: Human readable id, derived from the user-specified display name + canCopy: + type: optional + docs: >- + Define whether the script can be copied on site duplication and + transfer + default: false + displayName: + type: optional + docs: >- + User-facing name for the script. Must be between 1 and 50 alphanumeric + characters + hostedLocation: + type: optional + docs: URI for an externally hosted script location + integrityHash: + type: optional + docs: >- + Sub-Resource Integrity Hash. Only required for externally hosted + scripts (passed via hostedLocation) + createdOn: + type: optional + docs: Timestamp when the script version was created + lastUpdated: + type: optional + docs: Timestamp when the script version was last updated + version: + type: optional + docs: A Semantic Version (SemVer) string, denoting the version of the script + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Scripts: + docs: A list of scripts applied to a Site or a Page + type: list + CustomCodeBlockType: + enum: + - page + - site + docs: Whether the Custom Code script is applied at the Site-level or Page-level + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CustomCodeBlock: + docs: A specific instance of Custom Code applied to a Site or Page + properties: + siteId: + type: optional + docs: The Site ID where the custom code was applied + pageId: + type: optional + docs: The Page ID (if applied at Page-level) + type: + type: optional + docs: >- + Whether the Custom Code script is applied at the Site-level or + Page-level + scripts: optional + createdOn: + type: optional + docs: The date the Block was created + lastUpdated: + type: optional + docs: The date the Block was most recently updated + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ListCustomCodeBlocks: + docs: Custom Code Blocks corresponding to where scripts were applied + properties: + blocks: optional> + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + AssetVariant: + properties: + hostedUrl: + type: optional + docs: URL of where the asset variant is hosted + validation: + format: uri + originalFileName: + type: optional + docs: Original file name of the variant + displayName: + type: optional + docs: Display name of the variant + format: + type: optional + docs: format of the variant + width: + type: optional + docs: Width in pixels + height: + type: optional + docs: Height in pixels + quality: + type: optional + docs: Value between 0 and 100 representing the image quality + error: + type: optional + docs: Any associated validation errors + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Asset: + properties: + id: + type: optional + docs: Unique identifier for this asset + contentType: + type: optional + docs: File format type + size: + type: optional + docs: size in bytes + siteId: + type: optional + docs: Unique identifier for the site that hosts this asset + hostedUrl: + type: optional + docs: Link to the asset + validation: + format: uri + originalFileName: + type: optional + docs: Original file name at the time of upload + displayName: + type: optional + docs: Display name of the asset + lastUpdated: + type: optional + docs: Date the asset metadata was last updated + createdOn: + type: optional + docs: Date the asset metadata was created + variants: optional> + altText: + type: optional + docs: The visual description of the asset + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Assets: + docs: A list of assets + properties: + assets: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + AssetUploadUploadDetails: + docs: Metadata for uploading the asset binary + properties: + acl: optional + bucket: optional + X-Amz-Algorithm: optional + X-Amz-Credential: optional + X-Amz-Date: optional + key: optional + Policy: optional + X-Amz-Signature: optional + success_action_status: optional + content-type: optional + Cache-Control: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + AssetUpload: + properties: + uploadDetails: + type: optional + docs: Metadata for uploading the asset binary + contentType: optional + id: optional + parentFolder: + type: optional + docs: Parent folder for the asset + uploadUrl: + type: optional + validation: + format: uri + assetUrl: + type: optional + docs: S3 link to the asset + validation: + format: uri + hostedUrl: + type: optional + docs: Represents the link to the asset + validation: + format: uri + originalFileName: + type: optional + docs: >- + Original file name when uploaded. If not specified at time of upload, + it may be extracted from the raw file name + createdOn: + type: optional + docs: Date the asset metadata was created + lastUpdated: + type: optional + docs: Date the asset metadata was last updated + source: + openapi: ../../../openapi/referenced-specs/v2.yml + AssetFolder: + docs: Asset Folder details + properties: + id: + type: optional + docs: Unique identifier for the Asset Folder + displayName: + type: optional + docs: User visible name for the Asset Folder + parentFolder: + type: optional + docs: Pointer to parent Asset Folder (or null if root) + assets: + type: optional> + docs: Array of Asset instances in the folder + siteId: + type: optional + docs: The unique ID of the site the Asset Folder belongs to + createdOn: + type: optional + docs: Date that the Asset Folder was created on + lastUpdated: + type: optional + docs: Date that the Asset Folder was last updated on + source: + openapi: ../../../openapi/referenced-specs/v2.yml + AssetFolderList: + docs: The Asset Folders object + properties: + assetFolders: + type: optional> + docs: A list of Asset folders + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + TriggerType: + enum: + - form_submission + - site_publish + - page_created + - page_metadata_updated + - page_deleted + - ecomm_new_order + - ecomm_order_changed + - ecomm_inventory_changed + - user_account_added + - user_account_updated + - user_account_deleted + - collection_item_created + - collection_item_changed + - collection_item_deleted + - collection_item_unpublished + docs: > + * `form_submission` - Sends the [form_submission](#form_submission) event + + * `site_publish` - Sends a [site_publish](#site_publish) event + + * `page_created` - Send the [page_created](#page_created) event + + * `page_metadata_updated` - Sends the + [page_metadata_updated](#page_metadata_updated) event + + * `page_deleted` - Sends the [page_deleted](#page_deleted) event + + * `ecomm_new_order` - Sends the new [ecomm_new_order](#ecomm_new_order) + event + + * `ecomm_order_changed` - Sends the + [ecomm_order_changed](#ecomm_order_changed) event + + * `ecomm_inventory_changed` - Sends the + [ecomm_inventory_changed](#ecomm_inventory_changed) event + + * `user_account_added` - Sends the + [user_account_added](#user_account_added) event + + * `user_account_updated` - Sends the + [user_account_updated](#user_account_updated) event + + * `user_account_deleted` - Sends the + [user_account_deleted](#user_account_deleted) event + + * `collection_item_created` - Sends the + [collection_item_created](#collection_item_created) event + + * `collection_item_changed` - Sends the + [collection_item_changed](#collection_item_changed) event + + * `collection_item_deleted` - Sends the + [collection_item_deleted](#collection_item_deleted) event + + * `collection_item_unpublished` - Sends the + [collection_item_unpublished](#collection_item_unpublished) event + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WebhookFilter: + docs: >- + Only supported for the `form_submission` trigger type. Filter for the form + you want Webhooks to be sent for. + properties: + name: + type: optional + docs: The name of the form you'd like to recieve notifications for. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Webhook: + properties: + id: + type: optional + docs: Unique identifier for the Webhook registration + triggerType: optional + url: + type: optional + docs: URL to send the Webhook payload to + workspaceId: + type: optional + docs: Unique identifier for the Workspace the Webhook is registered in + siteId: + type: optional + docs: Unique identifier for the Site the Webhook is registered in + filter: + type: optional + docs: >- + Only supported for the `form_submission` trigger type. Filter for the + form you want Webhooks to be sent for. + lastTriggered: + type: optional + docs: Date the Webhook instance was last triggered + createdOn: + type: optional + docs: Date the Webhook registration was created + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WebhookList: + properties: + pagination: optional + webhooks: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FormFieldValueType: + enum: + - Plain + - Email + - Password + - Phone + - Number + docs: The field type + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FormFieldValue: + docs: An object containing field info for a specific fieldID. + properties: + displayName: + type: optional + docs: The field name displayed on the site + type: + type: optional + docs: The field type + placeholder: + type: optional + docs: The placeholder text for the field + userVisible: + type: optional + docs: Whether the field is visible to the user + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + FormField: + type: map + docs: A collection of form fields with additional properties. + FormResponseSettings: + docs: Settings for form responses + properties: + redirectUrl: + type: optional + docs: The url or path to redirect the user to after form submission + redirectMethod: + type: optional + docs: The HTTP request method to use for the redirectUrl (eg. POST or GET) + redirectAction: + type: optional + docs: The action to take after form submission + sendEmailConfirmation: + type: optional + docs: Whether to send an email confirmation to the user + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Form: + docs: A Webflow form + properties: + displayName: + type: optional + docs: The Form name displayed on the site + createdOn: + type: optional + docs: Date that the Form was created on + lastUpdated: + type: optional + docs: Date that the Form was last updated on + fields: + type: optional + docs: A collection of form field objects + responseSettings: + type: optional + docs: Settings for form responses + id: + type: optional + docs: The unique ID for the Form + siteId: + type: optional + docs: The unique ID of the Site the Form belongs to + siteDomainId: + type: optional + docs: The unique ID corresponding to the site's Domain name + pageId: + type: optional + docs: The unique ID for the Page on which the Form is placed + pageName: + type: optional + docs: The user-visible name of the Page where the Form is placed + formElementId: + type: optional + docs: The unique ID of the Form element + workspaceId: + type: optional + docs: The unique ID of the Workspace the Site belongs to + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FormList: + properties: + forms: optional> + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FormSubmission: + properties: + id: + type: optional + docs: The unique ID of the Form submission + displayName: + type: optional + docs: The Form name displayed on the site + siteId: + type: optional + docs: The unique ID of the Site the Form belongs to + workspaceId: + type: optional + docs: The unique ID of the Workspace the Site belongs to + dateSubmitted: + type: optional + docs: Date that the Form was submitted on + formResponse: + type: optional> + docs: The data submitted in the Form + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FormSubmissionList: + properties: + formSubmissions: optional> + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UserDataData: + properties: + name: + type: optional + docs: | + The name of the user + email: + type: optional + docs: | + The email address of the user + accept-privacy: + type: optional + docs: | + Boolean indicating if the user has accepted the privacy policy + accept-communications: + type: optional + docs: | + Boolean indicating if the user has accepted to receive communications + additionalProperties: + type: optional + docs: Custom user attributes + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + UserData: + docs: An object containing the User's basic info and custom fields + properties: + data: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UserStatus: + enum: + - invited + - verified + - unverified + docs: The status of the user + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UserAccessGroupsItemType: + enum: + - admin + - ecommerce + docs: | + The type of access group based on how it was assigned to the user. + * `admin` - Assigned to the user via API or in the designer + * `ecommerce` - Assigned to the user via an ecommerce purchase + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UserAccessGroupsItem: + docs: Access group slugs and types + properties: + slug: + type: optional + docs: Access group identifier for APIs + type: + type: optional + docs: | + The type of access group based on how it was assigned to the user. + * `admin` - Assigned to the user via API or in the designer + * `ecommerce` - Assigned to the user via an ecommerce purchase + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + User: + docs: > + The fields that define the schema for a given Item are based on the + Collection that Item belongs to. Beyond the user defined fields, there are + a handful of additional fields that are automatically created for all + items + properties: + id: + type: optional + docs: Unique identifier for the User + isEmailVerified: + type: optional + docs: Shows whether the user has verified their email address + lastUpdated: + type: optional + docs: The timestamp the user was updated + invitedOn: + type: optional + docs: The timestamp the user was invited + createdOn: + type: optional + docs: The timestamp the user was created + lastLogin: + type: optional + docs: The timestamp the user was logged in + status: + type: optional + docs: The status of the user + accessGroups: + type: optional> + docs: Access groups the user belongs to + data: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UserList: + docs: The list users results + properties: + count: + type: optional + docs: Number of users returned + limit: + type: optional + docs: The limit specified in the request + default: 10 + offset: + type: optional + docs: The offset specified for pagination + default: 0 + total: + type: optional + docs: Total number of users in the collection + users: + type: optional> + docs: List of Users for a Site + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UsersNotEnabled: unknown + DuplicateUserEmail: unknown + UserLimitReached: unknown + AccessGroup: + properties: + id: + type: optional + docs: Unique identifier for the Access Group + name: + type: optional + docs: Name of the the Access Group + shortId: + type: optional + docs: >- + Shortened unique identifier based on name, optimized for its use in + the user’s JWT + slug: + type: optional + docs: >- + Shortened unique identifier based on name, optimized for human + readability and public API use + createdOn: + type: optional + docs: The date the Access Group was created + source: + openapi: ../../../openapi/referenced-specs/v2.yml + AccessGroupList: + docs: The list access groups results + properties: + count: + type: optional + docs: Number of access groups returned + limit: + type: optional + docs: The limit specified in the request + default: 10 + offset: + type: optional + docs: The offset specified for pagination + default: 0 + total: + type: optional + docs: Total number of access groups in the collection + accessGroups: + type: optional> + docs: List of Site Access Groups + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SkuPropertyListEnumItem: + docs: Enumerated Product variants/Options for the SKU + properties: + id: + type: string + docs: Unique identifier for a Product variant/Option + name: + type: string + docs: Name of the Product variant/Option + slug: + type: string + docs: Slug for the Product variant/Option in the Site URL structure + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + SkuPropertyList: + docs: A variant/option type for a SKU + properties: + id: + type: string + docs: Unique identifier for a collection of Product Variants + name: + type: string + docs: Name of the collection of Product Variants + enum: + docs: >- + The individual Product variants that are contained within the + collection + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ProductFieldDataTaxCategory: + enum: + - value: standard-taxable + name: StandardTaxable + - value: standard-exempt + name: StandardExempt + - value: books-religious + name: BooksReligious + - value: books-textbook + name: BooksTextbook + - clothing + - value: clothing-swimwear + name: ClothingSwimwear + - value: digital-goods + name: DigitalGoods + - value: digital-service + name: DigitalService + - value: drugs-non-prescription + name: DrugsNonPrescription + - value: drugs-prescription + name: DrugsPrescription + - value: food-bottled-water + name: FoodBottledWater + - value: food-candy + name: FoodCandy + - value: food-groceries + name: FoodGroceries + - value: food-prepared + name: FoodPrepared + - value: food-soda + name: FoodSoda + - value: food-supplements + name: FoodSupplements + - value: magazine-individual + name: MagazineIndividual + - value: magazine-subscription + name: MagazineSubscription + - value: service-admission + name: ServiceAdmission + - value: service-advertising + name: ServiceAdvertising + - value: service-dry-cleaning + name: ServiceDryCleaning + - value: service-hairdressing + name: ServiceHairdressing + - value: service-installation + name: ServiceInstallation + - value: service-miscellaneous + name: ServiceMiscellaneous + - value: service-parking + name: ServiceParking + - value: service-printing + name: ServicePrinting + - value: service-professional + name: ServiceProfessional + - value: service-repair + name: ServiceRepair + - value: service-training + name: ServiceTraining + docs: Product tax class + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ProductFieldDataEcProductType: + enum: + - ff42fee0113744f693a764e3431a9cc2 + - f22027db68002190aef89a4a2b7ac8a1 + - c599e43b1a1c34d5a323aedf75d3adf6 + - b6ccc1830db4b1babeb06a9ac5f6dd76 + docs: >- + Product + types. Enums reflect the following values in order: Physical, Digital, + Service, Advanced" + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ProductFieldData: + docs: >- + Contains content-specific details for a product, covering both standard + (e.g., title, description) and custom fields tailored to the product + setup. + properties: + name: + type: optional + docs: Name of the Product + slug: + type: optional + docs: URL structure of the Product in your site. + description: + type: optional + docs: A description of your product + shippable: + type: optional + docs: Boolean determining if the Product is shippable + sku-properties: + type: optional> + docs: Variant types to include in SKUs + categories: + type: optional> + docs: The categories your product belongs to. + tax-category: + type: optional + docs: Product tax class + default-sku: + type: optional + docs: The default SKU associated with this product. + ec-product-type: + type: optional + docs: >- + Product + types. Enums reflect the following values in order: Physical, + Digital, Service, Advanced" + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Product: + docs: The Product object + properties: + id: + type: optional + docs: Unique identifier for the Product + cmsLocaleId: + type: optional + docs: Identifier for the locale of the CMS item + lastPublished: + type: optional + docs: The date the Product was last published + lastUpdated: + type: optional + docs: The date the Product was last updated + createdOn: + type: optional + docs: The date the Product was created + isArchived: + type: optional + docs: Boolean determining if the Product is set to archived + default: false + isDraft: + type: optional + docs: Boolean determining if the Product is set to draft + default: false + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SkuValueList: + type: map + docs: > + A dictionary that maps a SKU property to a SKU value. The key of the + dictionary is the SKU property ID, and the value is the SKU value ID. + SkuFieldDataPrice: + docs: price of SKU + properties: + value: + type: optional + docs: Price of SKU + unit: + type: optional + docs: Currency of Item + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + SkuFieldDataCompareAtPrice: + docs: comparison price of SKU + properties: + value: + type: optional + docs: Price of SKU + unit: + type: optional + docs: Currency of Item + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + SkuFieldDataEcSkuBillingMethod: + enum: + - value: one-time + name: OneTime + - subscription + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SkuFieldDataEcSkuSubscriptionPlanInterval: + enum: + - day + - week + - month + - year + docs: Interval of subscription renewal + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus: + enum: + - active + - inactive + - canceled + docs: The status of the plan + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SkuFieldDataEcSkuSubscriptionPlanPlansItem: + properties: + platform: + type: optional> + docs: The platform of the subscription plan + id: + type: optional + docs: The unique identifier of the plan + status: + type: optional + docs: The status of the plan + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + SkuFieldDataEcSkuSubscriptionPlan: + properties: + interval: + type: optional + docs: Interval of subscription renewal + frequency: + type: optional + docs: Frequncy of billing within interval + trial: + type: optional + docs: Number of days of a trial + plans: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + SkuFieldData: + docs: Standard and Custom fields for a SKU + properties: + sku-values: optional + name: + type: string + docs: Name of the Product + slug: + type: string + docs: URL structure of the Product in your site. + price: + type: SkuFieldDataPrice + docs: price of SKU + compare-at-price: + type: optional + docs: comparison price of SKU + ec-sku-billing-method: optional + ec-sku-subscription-plan: optional + track-inventory: + type: optional + docs: >- + A boolean indicating whether inventory for this product should be + tracked. + default: false + quantity: + type: optional + docs: Quantity of SKU that will be tracked as items are ordered. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Sku: + docs: The SKU object + properties: + id: + type: optional + docs: Unique identifier for the Product + cmsLocaleId: + type: optional + docs: Identifier for the locale of the CMS item + lastPublished: + type: optional + docs: The date the Product was last published + lastUpdated: + type: optional + docs: The date the Product was last updated + createdOn: + type: optional + docs: The date the Product was created + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ProductAndSkUs: + docs: A product and its SKUs. + properties: + product: optional + skus: + type: optional> + docs: A list of SKU Objects + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ProductAndSkUsList: + docs: Results from product list + properties: + items: + type: optional> + docs: >- + List of Item objects within the Collection. Contains product and skus + keys for each Item + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PublishStatus: + enum: + - staging + - live + docs: Indicate whether your Product should be set as "staging" or "live" + default: staging + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderPrice: + properties: + unit: + type: optional + docs: The three-letter ISO currency code + value: + type: optional + docs: The numeric value in the base unit of the currency + string: + type: optional + docs: The user-facing string representation of the amount + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderAddressType: + enum: + - shipping + - billing + docs: The type of the order address (billing or shipping) + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderAddressJapanType: + enum: + - kana + - kanji + docs: >- + Represents a Japan-only address format. This field will only appear on + orders placed from Japan. + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderAddress: + docs: A customer address + properties: + type: + type: optional + docs: The type of the order address (billing or shipping) + japanType: + type: optional + docs: >- + Represents a Japan-only address format. This field will only appear on + orders placed from Japan. + addressee: + type: optional + docs: Display name on the address + line1: + type: optional + docs: The first line of the address + line2: + type: optional + docs: The second line of the address + city: + type: optional + docs: The city of the address. + state: + type: optional + docs: The state or province of the address + country: + type: optional + docs: The country of the address + postalCode: + type: optional + docs: The postal code of the address + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderPurchasedItemVariantImageFileVariantsItem: + properties: + url: + type: optional + docs: The hosted location for the Variant's image + validation: + format: uri + originalFileName: optional + size: + type: optional + docs: The image size in bytes + width: + type: optional + docs: The image width in pixels + height: + type: optional + docs: The image height in pixels + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + OrderPurchasedItemVariantImageFile: + properties: + size: + type: optional + docs: The image size in bytes + originalFileName: + type: optional + docs: the original name of the image + createdOn: + type: optional + docs: The creation timestamp of the image + contentType: + type: optional + docs: The MIME type of the image + width: + type: optional + docs: The image width in pixels + height: + type: optional + docs: The image height in pixels + variants: + type: optional> + docs: Variants of the supplied image + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + OrderPurchasedItemVariantImage: + properties: + url: + type: optional + docs: The hosted location for the Variant's image + validation: + format: uri + file: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + OrderPurchasedItem: + docs: An Item that was purchased + properties: + count: + type: optional + docs: Number of Item purchased. + rowTotal: + type: optional + docs: The total for the row + productId: + type: optional + docs: The unique identifier for the Product + productName: + type: optional + docs: User-facing name of the Product + productSlug: + type: optional + docs: Slug for the Product + variantId: + type: optional + docs: Identifier for the Product Variant (SKU) + variantName: + type: optional + docs: User-facing name of the Product Variant (SKU) + variantSlug: + type: optional + docs: Slug for the Product Variant (SKU) + variantSKU: + type: optional + docs: The user-defined custom SKU of the Product Variant (SKU) + variantImage: optional + variantPrice: + type: optional + docs: The price corresponding to the variant + weight: + type: optional + docs: The physical weight of the variant if provided, or null + width: + type: optional + docs: The physical width of the variant if provided, or null + height: + type: optional + docs: The physical height of the variant if provided, or null + length: + type: optional + docs: The physical length of the variant if provided, or null + source: + openapi: ../../../openapi/referenced-specs/v2.yml + StripeDetails: + docs: >- + An object with various Stripe IDs, useful for linking into the stripe + dashboard. + properties: + subscriptionId: + type: optional + docs: Stripe-generated identifier for the Subscription + paymentMethod: + type: optional + docs: Stripe-generated identifier for the PaymentMethod used + paymentIntentId: + type: optional + docs: Stripe-generated identifier for the PaymentIntent, or null + customerId: + type: optional + docs: Stripe-generated customer identifier, or null + chargeId: + type: optional + docs: Stripe-generated charge identifier, or null + disputeId: + type: optional + docs: Stripe-generated dispute identifier, or null + refundId: + type: optional + docs: Stripe-generated refund identifier, or null + refundReason: + type: optional + docs: Stripe-generated refund reason, or null + source: + openapi: ../../../openapi/referenced-specs/v2.yml + StripeCardBrand: + enum: + - Visa + - value: American Express + name: AmericanExpress + - MasterCard + - Discover + - JCB + - value: Diners Club + name: DinersClub + - Unknown + docs: The card's brand (ie. credit card network) + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + StripeCardExpires: + docs: The card's expiration date. + properties: + year: + type: optional + docs: Year that the card expires + month: + type: optional + docs: Month that the card expires + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + StripeCard: + docs: > + Details on the card used to fulfill this order, if this order was + finalized with Stripe. + properties: + last4: + type: optional + docs: The last 4 digits on the card as a string + brand: + type: optional + docs: The card's brand (ie. credit card network) + ownerName: + type: optional + docs: The name on the card. + expires: + type: optional + docs: The card's expiration date. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PaypalDetails: + properties: + orderId: + type: optional + docs: PayPal order identifier + payerId: + type: optional + docs: PayPal payer identifier + captureId: + type: optional + docs: PayPal capture identifier + refundId: + type: optional + docs: PayPal refund identifier + refundReason: + type: optional + docs: PayPal-issued reason for the refund + disputeId: + type: optional + docs: PayPal dispute identifier + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderStatus: + enum: + - pending + - unfulfilled + - fulfilled + - disputed + - value: dispute-lost + name: DisputeLost + - refunded + docs: | + The status of the Order + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderDisputeLastStatus: + enum: + - warning_needs_response + - warning_under_review + - warning_closed + - needs_response + - under_review + - charge_refunded + - won + - lost + docs: > + If an order was disputed by the customer, then this key will be set with + the [dispute's status](https://stripe.com/docs/api#dispute_object-status). + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderCustomerInfo: + docs: An object with the keys `fullName` and `email`. + properties: + fullName: + type: optional + docs: The full name of the Customer + email: + type: optional + docs: The Customer's email address + validation: + format: email + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + OrderMetadata: + properties: + isBuyNow: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + OrderTotalsExtrasItemType: + enum: + - discount + - value: discount-shipping + name: DiscountShipping + - shipping + - tax + docs: The type of extra item this is. + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderTotalsExtrasItem: + docs: Extra order items, includes discounts, shipping, and taxes. + properties: + type: + type: optional + docs: The type of extra item this is. + name: + type: optional + docs: A human-readable (but English) name for this extra charge. + description: + type: optional + docs: A human-readable (but English) description of this extra charge. + price: + type: optional + docs: The price for the item + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + OrderTotals: + docs: An object describing various pricing totals + properties: + subtotal: + type: optional + docs: The subtotal price + extras: + type: optional> + docs: An array of extra items, includes discounts, shipping, and taxes. + total: + type: optional + docs: The total price + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + OrderDownloadFilesItem: + properties: + id: + type: optional + docs: The unique identifier for the downloadable file + name: + type: optional + docs: The user-facing name for the downloadable file + url: + type: optional + docs: The hosted location for the downloadable file + validation: + format: uri + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Order: + properties: + orderId: + type: optional + docs: | + The order ID. Will usually be 6 hex characters, but can also be 9 + hex characters if the site has a very large number of Orders. + Randomly assigned. + status: + type: optional + docs: | + The status of the Order + comment: + type: optional + docs: >- + A comment string for this Order, which is editable by API user (not + used by Webflow). + orderComment: + type: optional + docs: A comment that the customer left when making their Order + acceptedOn: + type: optional + docs: The ISO8601 timestamp that an Order was placed. + fulfilledOn: + type: optional + docs: > + When an Order is marked as 'fulfilled', this field represents the + timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. + refundedOn: + type: optional + docs: >- + When an Order is marked as 'refunded', this field represents the + timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. + disputedOn: + type: optional + docs: > + When an Order is marked as 'disputed', this field represents the + timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. + disputeUpdatedOn: + type: optional + docs: > + If an Order has been disputed by the customer, this key will be set to + the ISO8601 timestamp of the last update received. If the Order is not + disputed, the key will be null. + disputeLastStatus: + type: optional + docs: > + If an order was disputed by the customer, then this key will be set + with the [dispute's + status](https://stripe.com/docs/api#dispute_object-status). + customerPaid: + type: optional + docs: The total paid by the customer + netAmount: + type: optional + docs: The net amount after application fees + applicationFee: + type: optional + docs: The application fee assessed by the platform + allAddresses: + type: optional> + docs: All addresses provided by the customer during the ordering flow. + shippingAddress: + type: optional + docs: The shipping address + billingAddress: + type: optional + docs: The billing address + shippingProvider: + type: optional + docs: > + A string editable by the API user to note the shipping provider used + (not used by Webflow). + shippingTracking: + type: optional + docs: > + A string editable by the API user to note the shipping tracking number + for the order (not used by Webflow). + shippingTrackingURL: + type: optional + validation: + format: uri + customerInfo: + type: optional + docs: An object with the keys `fullName` and `email`. + purchasedItems: + type: optional> + docs: An array of all things that the Customer purchased. + purchasedItemsCount: + type: optional + docs: The sum of all 'count' fields in 'purchasedItems'. + stripeDetails: optional + stripeCard: optional + paypalDetails: optional + customData: + type: optional>> + docs: > + An array of additional inputs for custom order data gathering. Each + object in the array represents an input with a name, and a textInput, + textArea, or checkbox value. + metadata: optional + isCustomerDeleted: + type: optional + docs: > + A boolean indicating whether the customer has been deleted from the + site. + isShippingRequired: + type: optional + docs: > + A boolean indicating whether the order contains one or more purchased + items that require shipping. + hasDownloads: + type: optional + docs: > + A boolean indicating whether the order contains one or more purchased + items that are downloadable. + paymentProcessor: + type: optional + docs: | + A string indicating the payment processor used for this order. + totals: + type: optional + docs: An object describing various pricing totals + downloadFiles: + type: optional> + docs: An array of downloadable file objects. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderList: + docs: Results from order list + properties: + orders: + type: optional> + docs: List of orders + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + InventoryItemInventoryType: + enum: + - infinite + - finite + docs: infinite or finite + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + InventoryItem: + docs: The availabile inventory for an item + properties: + id: + type: optional + docs: Unique identifier for a SKU item + quantity: + type: optional + docs: >- + Total quantity of items remaining in inventory (if inventoryType is + finite) + inventoryType: + type: optional + docs: infinite or finite + source: + openapi: ../../../openapi/referenced-specs/v2.yml + EcommerceSettings: + docs: Ecommerce settings for a Webflow Site + properties: + siteId: + type: optional + docs: The identifier of the Site + createdOn: + type: optional + docs: Date that the Site was created on + defaultCurrency: + type: optional + docs: The three-letter ISO currency code for the Site + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/accessGroups.yml b/.mock/definition/accessGroups.yml new file mode 100644 index 0000000..d8828f8 --- /dev/null +++ b/.mock/definition/accessGroups.yml @@ -0,0 +1,80 @@ +types: + AccessGroupsListRequestSort: + enum: + - value: CreatedOn + name: CreatedOnAscending + docs: Sorts users in ascending order based on their created date + - value: '-CreatedOn' + name: CreatedOnDescending + docs: Sorts users in descending order based on their created date + source: + openapi: ../../../openapi/referenced-specs/v2.yml +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/accessgroups + method: GET + auth: true + docs: | + Get a list of access groups for a site + + Required scope | `users:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Access Groups + request: + name: AccessGroupsListRequest + query-parameters: + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + sort: + type: optional + docs: | + Sort string to use when ordering access groups + Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) + response: + docs: Request was successful + type: root.AccessGroupList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + count: 1 + limit: 10 + offset: 0 + total: 1 + accessGroups: + - id: 62be58d404be8a6cc900c081 + name: Research Team + shortId: rt + slug: hitchhikers-guide-research-team + createdOn: '2022-08-01T19:41:48Z' + - id: 65a96161991e77bbb4a6c573 + name: Admin + shortId: ad + slug: admin + createdOn: '2022-08-01T19:41:48Z' + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/api.yml b/.mock/definition/api.yml new file mode 100644 index 0000000..aee9acd --- /dev/null +++ b/.mock/definition/api.yml @@ -0,0 +1,13 @@ +name: api +error-discrimination: + strategy: status-code +display-name: Data API +environments: + Default: https://api.webflow.com/v2 +default-environment: Default +auth-schemes: + BearerToken: + scheme: bearer + token: + name: accessToken +auth: BearerToken diff --git a/.mock/definition/assets.yml b/.mock/definition/assets.yml new file mode 100644 index 0000000..35392ec --- /dev/null +++ b/.mock/definition/assets.yml @@ -0,0 +1,415 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/assets + method: GET + auth: true + docs: | + List assets for a given site + + Required scope | `assets:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Assets + response: + docs: Request was successful + type: root.Assets + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + assets: + - id: 63e5889e7fe4eafa7384cea4 + contentType: image/png + size: 2212772 + siteId: 63938b302ea6b0aa6f3d8745 + hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg + originalFileName: Candy-Wrapper.svg + displayName: 63e5889e7fe4eafa7384cea4_Candy-Wrapper.png + lastUpdated: '2023-03-01T23:42:57Z' + createdOn: '2023-02-09T23:58:22Z' + variants: + - hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + originalFileName: >- + Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + displayName: >- + 660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + format: png + width: 500 + height: 900 + quality: 100 + altText: A red chair + create: + path: /sites/{site_id}/assets + method: POST + auth: true + docs: > + Create a new asset entry. + + + + This endpoint generates a response with the following information: + `uploadUrl` and `uploadDetails`. + + You can use these two properties to [upload the file to Amazon s3 by + making a + POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) + + request to the `uploadUrl` with the `uploadDetails` object as your + header information in the request. + + + Required scope | `assets:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Create Asset Metadata + request: + name: AssetsCreateRequest + body: + properties: + fileName: + type: string + docs: >- + File name including file extension. File names must be less than + 100 characters. + fileHash: + type: string + docs: MD5 hash of the file + parentFolder: + type: optional + docs: ID of the Asset folder (optional) + content-type: application/json + response: + docs: Request was successful + type: root.AssetUpload + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + fileName: file.png + fileHash: 3c7d87c9575702bc3b1e991f4d3c638e + response: + body: + uploadDetails: + acl: public-read + bucket: webflow-bucket-name + X-Amz-Algorithm: AWS4-HMAC-SHA256 + X-Amz-Credential: ///s3/aws4_request + X-Amz-Date: + key: /_ + Policy: + X-Amz-Signature: + success_action_status: '201' + content-type: image/png + Cache-Control: max-age=31536000, must-revalidate + contentType: image/png + id: 64358b9544249dc43d37d2b7 + parentFolder: 6436b1ce5281cace05b65aea + uploadUrl: >- + https://s3.amazonaws.com/webflow-dev-assets/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png + assetUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d907ab9e91e3e9f56385e_paranoidAndroid-2024.png + hostedUrl: >- + https://d1otoma47x30pg.cloudfront.net/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png + originalFileName: file.png + createdOn: '2023-04-11T16:32:21Z' + lastUpdated: '2023-04-12T20:31:03Z' + get: + path: /assets/{asset_id} + method: GET + auth: true + docs: | + Get an Asset + + Required scope | `assets:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + asset_id: + type: string + docs: Unique identifier for an Asset on a site + display-name: Get Asset + response: + docs: Request was successful + type: root.Asset + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + asset_id: 580e63fc8c9a982ac9b8b745 + response: + body: + id: 55131cd036c09f7d07883dfc + contentType: image/png + size: 1500 + siteId: 62749158efef318abc8d5a0f + hostedUrl: example.com/hostedimage.png + originalFileName: image.png + displayName: example-image-123.png + lastUpdated: '2016-09-06T21:12:22Z' + createdOn: '2016-09-02T23:26:22Z' + variants: + - hostedUrl: example.com/hostedimage.png + originalFileName: image.png + displayName: A brown dog + format: format + width: 1500 + height: 900 + quality: 1 + error: error + altText: A red chair + delete: + path: /assets/{asset_id} + method: DELETE + auth: true + docs: | + Delete an Asset + + Required Scope: `assets: write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + asset_id: + type: string + docs: Unique identifier for an Asset on a site + display-name: Delete Asset + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + asset_id: 580e63fc8c9a982ac9b8b745 + update: + path: /assets/{asset_id} + method: PATCH + auth: true + docs: | + Update an Asset + + Required scope | `assets:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + asset_id: + type: string + docs: Unique identifier for an Asset on a site + display-name: Update Asset + request: + name: AssetsUpdateRequest + body: + properties: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + displayName: + type: optional + docs: A human readable name for the asset + content-type: application/json + response: + docs: Request was successful + type: root.Asset + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + asset_id: 580e63fc8c9a982ac9b8b745 + request: {} + response: + body: + id: 55131cd036c09f7d07883dfc + contentType: image/png + size: 1500 + siteId: 62749158efef318abc8d5a0f + hostedUrl: example.com/hostedimage.png + originalFileName: image.png + displayName: example-image-123.png + lastUpdated: '2016-09-06T21:12:22Z' + createdOn: '2016-09-02T23:26:22Z' + variants: + - hostedUrl: example.com/hostedimage.png + originalFileName: image.png + displayName: A brown dog + format: format + width: 1500 + height: 900 + quality: 1 + error: error + altText: A red chair + list-folders: + path: /sites/{site_id}/asset_folders + method: GET + auth: true + docs: | + List Asset Folders within a given site + + Required scope | `assets:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Asset Folders + response: + docs: Request was successful + type: root.AssetFolderList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + assetFolders: + - id: 6390c49774a71f0e3c1a08ee + displayName: emoji icons + parentFolder: 6390c49774a71f99f21a08eb + assets: + - 63e5889e7fe4eafa7384cea4 + - 659595234426a9fcbad57043 + siteId: 6390c49674a71f84b51a08d8 + createdOn: '2018-10-14T21:55:49Z' + lastUpdated: '2022-12-07T16:51:37Z' + pagination: + limit: 1 + offset: 0 + total: 1 + create-folder: + path: /sites/{site_id}/asset_folders + method: POST + auth: true + docs: | + Create an Asset Folder within a given site + + Required scope | `assets:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Create Asset Folder + request: + name: AssetsCreateFolderRequest + body: + properties: + displayName: + type: string + docs: A human readable name for the Asset Folder + parentFolder: + type: optional + docs: >- + An (optional) pointer to a parent Asset Folder (or null for + root) + content-type: application/json + response: + docs: Request was successful + type: root.AssetFolder + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + displayName: my asset folder + response: + body: + id: 6390c49774a71f0e3c1a08ee + displayName: emoji icons + parentFolder: 6390c49774a71f99f21a08eb + assets: + - 63e5889e7fe4eafa7384cea4 + - 659595234426a9fcbad57043 + siteId: 6390c49674a71f84b51a08d8 + createdOn: '2018-10-14T21:55:49Z' + lastUpdated: '2022-12-07T16:51:37Z' + get-folder: + path: /asset_folders/{asset_folder_id} + method: GET + auth: true + docs: | + Get details about a specific Asset Folder + + Required scope | `assets:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + asset_folder_id: + type: string + docs: Unique identifier for an Asset Folder + display-name: Get Asset Folder + response: + docs: Request was successful + type: root.AssetFolder + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + asset_folder_id: 6390c49774a71f0e3c1a08ee + response: + body: + id: 6390c49774a71f0e3c1a08ee + displayName: emoji icons + parentFolder: 6390c49774a71f99f21a08eb + assets: + - 63e5889e7fe4eafa7384cea4 + - 659595234426a9fcbad57043 + siteId: 6390c49674a71f84b51a08d8 + createdOn: '2018-10-14T21:55:49Z' + lastUpdated: '2022-12-07T16:51:37Z' + source: + openapi: ../../../openapi/referenced-specs/v2.yml + display-name: Assets +docs: Assets are files that are uploaded to your Webflow account. diff --git a/.mock/definition/collections.yml b/.mock/definition/collections.yml new file mode 100644 index 0000000..661b54b --- /dev/null +++ b/.mock/definition/collections.yml @@ -0,0 +1,186 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/collections + method: GET + auth: true + docs: | + List of all Collections within a Site. + + Required scope | `cms:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Collections + response: + docs: Request was successful + type: root.CollectionList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + collections: + - id: 63692ab61fb2852f582ba8f5 + displayName: Products + singularName: Product + slug: product + createdOn: '2019-06-12T13:35:14Z' + lastUpdated: '2022-11-17T15:08:50Z' + - id: 63692ab61fb2856e6a2ba8f6 + displayName: Categories + singularName: Category + slug: category + createdOn: '2019-06-12T13:35:14Z' + lastUpdated: '2022-11-17T15:08:50Z' + - id: 63692ab61fb285a8562ba8f4 + displayName: SKUs + singularName: SKU + slug: sku + createdOn: '2019-06-12T13:35:14Z' + lastUpdated: '2022-11-17T15:08:50Z' + create: + path: /sites/{site_id}/collections + method: POST + auth: true + docs: | + Create a Collection for a site. + + Required scope | `cms:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Create Collection + request: + name: CollectionsCreateRequest + body: + properties: + displayName: + type: string + docs: Name of the collection. Each collection name must be distinct. + singularName: + type: string + docs: Singular name of each item. + slug: + type: optional + docs: Part of a URL that identifier + content-type: application/json + response: + docs: Request was successful + type: root.Collection + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + displayName: Blog Posts + singularName: Blog Post + slug: posts + response: + body: + id: 580e63fc8c9a982ac9b8b745 + displayName: Blog Posts + singularName: Blog Post + slug: post + createdOn: '2016-10-24T19:41:48Z' + lastUpdated: '2016-10-24T19:42:38Z' + fields: + - id: 23cc2d952d4e4631ffd4345d2743db4e + isRequired: true + isEditable: true + type: PlainText + slug: name + displayName: Name + helpText: helpText + get: + path: /collections/{collection_id} + method: GET + auth: true + docs: | + Get the full details of a collection from its ID. + + Required scope | `cms:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: Get Collection Details + response: + docs: Request was successful + type: root.Collection + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + response: + body: + id: 580e63fc8c9a982ac9b8b745 + displayName: Blog Posts + singularName: Blog Post + slug: post + createdOn: '2016-10-24T19:41:48Z' + lastUpdated: '2016-10-24T19:42:38Z' + fields: + - id: 23cc2d952d4e4631ffd4345d2743db4e + isRequired: true + isEditable: true + type: PlainText + slug: name + displayName: Name + helpText: helpText + delete: + path: /collections/{collection_id} + method: DELETE + auth: true + docs: | + Delete a collection using its ID. + + Required scope | `cms:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: Delete Collection + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + source: + openapi: ../../../openapi/referenced-specs/v2.yml + display-name: Collections +docs: Collections are CMS collections of items. diff --git a/.mock/definition/collections/fields.yml b/.mock/definition/collections/fields.yml new file mode 100644 index 0000000..08dc554 --- /dev/null +++ b/.mock/definition/collections/fields.yml @@ -0,0 +1,189 @@ +types: + FieldCreateType: + enum: + - Color + - DateTime + - Email + - ExtFileRef + - File + - Image + - Link + - MultiImage + - Number + - Phone + - PlainText + - RichText + - Switch + - Video + docs: Choose these appropriate field type for your collection data + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + create: + path: /collections/{collection_id}/fields + method: POST + auth: true + docs: > + Create a custom field in a collection. + + + Slugs must be all lowercase letters without spaces. + + If you pass a string with uppercase letters and/or spaces to the "Slug" + property, Webflow will + + convert the slug to lowercase and replace spaces with "-." + + + Only some field types can be created through the API. + + This endpoint does not currently support bulk creation. + + + Required scope | `cms:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: Create Collection Field + request: + name: FieldCreate + body: + properties: + isRequired: + type: optional + docs: define whether a field is required in a collection + type: + type: FieldCreateType + docs: Choose these appropriate field type for your collection data + displayName: + type: string + docs: The name of a field + helpText: + type: optional + docs: Additional text to help anyone filling out this field + content-type: application/json + response: + docs: Request was successful + type: root.Field + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + isRequired: false + type: RichText + displayName: Post Body + helpText: Add the body of your post here + response: + body: + id: 75821f618da60c18383330bcc0ca488b + isRequired: false + isEditable: true + type: RichText + slug: post-body + displayName: Post Body + helpText: Add the body of your post here + delete: + path: /collections/{collection_id}/fields/{field_id} + method: DELETE + auth: true + docs: > + Delete a custom field in a collection. This endpoint does not currently + support bulk deletion. + + + Required scope | `cms:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + field_id: + type: string + docs: Unique identifier for a Field in a collection + display-name: Delete Collection Field + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + field_id: 580e63fc8c9a982ac9b8b745 + update: + path: /collections/{collection_id}/fields/{field_id} + method: PATCH + auth: true + docs: | + Update a custom field in a collection. + + Required scope | `cms:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + field_id: + type: string + docs: Unique identifier for a Field in a collection + display-name: Update Collection Field + request: + name: FieldUpdate + body: + properties: + isRequired: + type: optional + docs: Define whether a field is required in a collection + displayName: + type: optional + docs: The name of a field + helpText: + type: optional + docs: Additional text to help anyone filling out this field + content-type: application/json + response: + docs: Request was successful + type: root.Field + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + field_id: 580e63fc8c9a982ac9b8b745 + request: + isRequired: false + displayName: Post Body + helpText: Add the body of your post here + response: + body: + id: 75821f618da60c18383330bcc0ca488b + isRequired: false + isEditable: true + type: RichText + slug: post-body + displayName: Post Body + helpText: Add the body of your post here + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/collections/items.yml b/.mock/definition/collections/items.yml new file mode 100644 index 0000000..f765817 --- /dev/null +++ b/.mock/definition/collections/items.yml @@ -0,0 +1,1628 @@ +types: + ItemsListItemsRequestSortBy: + enum: + - lastPublished + - name + - slug + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ItemsListItemsRequestSortOrder: + enum: + - asc + - desc + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Multiple Items: + properties: + items: + type: optional> + docs: An array of items to create + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ItemsCreateItemRequest: + discriminated: false + union: + - root.CollectionItemPostSingle + - Multiple Items + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ItemsDeleteItemsRequestItemsItem: + properties: + id: + type: string + docs: Unique identifier for the Item + cmsLocaleIds: + type: optional> + docs: Array of identifiers for the locales where the item will be created + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ItemsListItemsLiveRequestSortBy: + enum: + - lastPublished + - name + - slug + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ItemsListItemsLiveRequestSortOrder: + enum: + - asc + - desc + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Multiple Live Items: + properties: + items: + type: optional> + docs: List of collection items to create + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ItemsCreateItemLiveRequest: + discriminated: false + union: + - root.CollectionItem + - Multiple Live Items + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ItemsDeleteItemsLiveRequestItemsItem: + properties: + itemId: + type: string + docs: Unique identifier for the Item + cmsLocaleIds: + type: optional> + docs: Array of identifiers for the locales where the item will be created + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Single CMS Item: + properties: + name: + type: string + docs: The name of the item. + slug: + type: string + docs: >- + URL slug for the item in your site. + + Note: Updating the item slug will break all links referencing the old + slug. + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CreateBulkCollectionItemRequestBodyFieldDataItem: + docs: A single CMS item to create + properties: + name: + type: string + docs: The name of the item. + slug: + type: string + docs: >- + URL slug for the item in your site. + + Note: Updating the item slug will break all links referencing the old + slug. + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CreateBulkCollectionItemRequestBodyFieldData: + discriminated: false + union: + - Single CMS Item + - docs: A list of CMS items to create + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ItemsPublishItemResponse: + properties: + publishedItemIds: optional> + errors: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + list-items: + path: /collections/{collection_id}/items + method: GET + auth: true + docs: | + List of all Items within a Collection. + + Required scope | `CMS:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: List Collection Items + request: + name: ItemsListItemsRequest + query-parameters: + cmsLocaleId: + type: optional + docs: >- + Unique identifier for a CMS Locale. This UID is different from the + Site locale identifier and is listed as `cmsLocaleId` in the Sites + response. To query multiple locales, input a comma separated + string. + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + name: + type: optional + docs: The name of the item(s) + slug: + type: optional + docs: The slug of the item + sortBy: + type: optional + docs: Sort results by the provided value + sortOrder: + type: optional + docs: Sorts the results by asc or desc + response: + docs: Request was successful + type: root.CollectionItemList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + response: + body: + items: + - id: 62b720ef280c7a7a3be8cabe + cmsLocaleId: 66f6e966c9e1dc700a857ca3 + lastPublished: '2022-06-30T13:35:20.878Z' + lastUpdated: '2022-06-25T14:51:27.809Z' + createdOn: '2022-06-25T14:51:27.809Z' + isArchived: false + isDraft: false + fieldData: + name: Senior Data Analyst + slug: senior-data-analyst + url: https://boards.greenhouse.io/webflow/jobs/26567701 + department: Data + - id: 62c880ef281c7b7b4cf9dabc + cmsLocaleId: 66f6e966c9e1dc700a857ca3 + lastPublished: '2023-04-15T10:25:18.123Z' + lastUpdated: '2023-04-10T11:45:30.567Z' + createdOn: '2023-04-10T11:45:30.567Z' + isArchived: false + isDraft: false + fieldData: + name: Product Manager + slug: product-manager + url: https://boards.greenhouse.io/webflow/jobs/31234567 + department: Product + pagination: + limit: 25 + offset: 0 + total: 2 + create-item: + path: /collections/{collection_id}/items + method: POST + auth: true + docs: > + Create Item(s) in a Collection. + + + + To create items across multiple locales, please use [this + endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + + + Required scope | `CMS:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: Create Collection Item(s) + request: + body: ItemsCreateItemRequest + content-type: application/json + response: + docs: Request was successful + type: root.CollectionItem + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - name: SingleItem + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + isArchived: false + isDraft: false + fieldData: + name: Pan Galactic Gargle Blaster Recipe + slug: pan-galactic-gargle-blaster + date: '2022-11-18T00:00:00.000Z' + featured: true + color: '#db4b68' + response: + body: + id: 42b720ef280c7a7a3be8cabe + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2022-11-29T16:22:43.159Z' + lastUpdated: '2022-11-17T17:19:43.282Z' + createdOn: '2022-11-17T17:11:57.148Z' + isArchived: false + isDraft: false + fieldData: + name: Pan Galactic Gargle Blaster Recipe + slug: pan-galactic-gargle-blaster + color: '#db4b68' + date: '2022-11-18T00:00:00.000Z' + featured: true + - name: MultipleItems + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - isArchived: false + isDraft: false + fieldData: + name: Senior Data Analyst + slug: senior-data-analyst + url: https://boards.greenhouse.io/webflow/jobs/26567701 + department: Data + - isArchived: false + isDraft: false + fieldData: + name: Product Manager + slug: product-manager + url: https://boards.greenhouse.io/webflow/jobs/31234567 + department: Product + response: + body: + id: id + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + isArchived: true + isDraft: true + fieldData: + name: My new item + slug: my-new-item + date: '2022-11-18T00:00:00.000Z' + featured: false + color: '#db4b68' + delete-items: + path: /collections/{collection_id}/items + method: DELETE + auth: true + docs: > + Delete Items from a Collection. + + + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the + items are localized, items will be deleted only in the primary locale. + + + Required scope | `CMS:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: Delete Collection Items + request: + name: ItemsDeleteItemsRequest + body: + properties: + items: optional> + content-type: application/json + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: {} + update-items: + path: /collections/{collection_id}/items + method: PATCH + auth: true + docs: > + Update a single item or multiple items (up to 100) in a Collection. + + + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the + items are localized, items will be updated only in the primary locale. + + + Required scope | `CMS:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: Update Collection Items + request: + name: ItemsUpdateItemsRequest + body: + properties: + items: optional> + content-type: application/json + response: + docs: Request was successful + type: root.CollectionItem + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - name: LocalizedItems + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Ne Paniquez Pas + slug: ne-paniquez-pas + featured: false + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: No Entrar en Pánico + slug: no-entrar-en-panico + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Au Revoir et Merci pour Tous les Poissons + slug: au-revoir-et-merci + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: Hasta Luego y Gracias por Todo el Pescado + slug: hasta-luego-y-gracias + featured: false + response: + body: + id: id + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + isArchived: true + isDraft: true + fieldData: + name: My new item + slug: my-new-item + date: '2022-11-18T00:00:00.000Z' + featured: false + color: '#db4b68' + - name: MultipleItems + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 580e64008c9a982ac9b8b754 + isArchived: false + isDraft: false + fieldData: + name: Senior Data Analyst + slug: senior-data-analyst + url: https://boards.greenhouse.io/webflow/jobs/26567701 + department: Data + - id: 580e64008c9a982ac9b8b754 + isArchived: false + isDraft: false + fieldData: + name: Product Manager + slug: product-manager + url: https://boards.greenhouse.io/webflow/jobs/31234567 + department: Product + response: + body: + id: id + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + isArchived: true + isDraft: true + fieldData: + name: My new item + slug: my-new-item + date: '2022-11-18T00:00:00.000Z' + featured: false + color: '#db4b68' + - name: Multiple items updated across multiple locales + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Ne Paniquez Pas + slug: ne-paniquez-pas + featured: false + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: No Entrar en Pánico + slug: no-entrar-en-panico + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Au Revoir et Merci pour Tous les Poissons + slug: au-revoir-et-merci + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: Hasta Luego y Gracias por Todo el Pescado + slug: hasta-luego-y-gracias + featured: false + response: + body: + id: id + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + isArchived: true + isDraft: true + fieldData: + name: My new item + slug: my-new-item + date: '2022-11-18T00:00:00.000Z' + featured: false + color: '#db4b68' + - name: Mulitple items updated in a single locale + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Ne Paniquez Pas + slug: ne-paniquez-pas + featured: false + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: No Entrar en Pánico + slug: no-entrar-en-panico + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Au Revoir et Merci pour Tous les Poissons + slug: au-revoir-et-merci + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: Hasta Luego y Gracias por Todo el Pescado + slug: hasta-luego-y-gracias + featured: false + response: + body: + id: id + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + isArchived: true + isDraft: true + fieldData: + name: My new item + slug: my-new-item + date: '2022-11-18T00:00:00.000Z' + featured: false + color: '#db4b68' + list-items-live: + path: /collections/{collection_id}/items/live + method: GET + auth: true + docs: | + List of all live Items within a Collection. + + Required scope | `CMS:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: List Live Collection Items + request: + name: ItemsListItemsLiveRequest + query-parameters: + cmsLocaleId: + type: optional + docs: >- + Unique identifier for a CMS Locale. This UID is different from the + Site locale identifier and is listed as `cmsLocaleId` in the Sites + response. To query multiple locales, input a comma separated + string. + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + name: + type: optional + docs: The name of the item(s) + slug: + type: optional + docs: The slug of the item + sortBy: + type: optional + docs: Sort results by the provided value + sortOrder: + type: optional + docs: Sorts the results by asc or desc + response: + docs: Request was successful + type: root.CollectionItemList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + response: + body: + items: + - id: 62b720ef280c7a7a3be8cabe + cmsLocaleId: 66f6e966c9e1dc700a857ca3 + lastPublished: '2022-06-30T13:35:20.878Z' + lastUpdated: '2022-06-25T14:51:27.809Z' + createdOn: '2022-06-25T14:51:27.809Z' + isArchived: false + isDraft: false + fieldData: + name: Senior Data Analyst + slug: senior-data-analyst + url: https://boards.greenhouse.io/webflow/jobs/26567701 + department: Data + - id: 62c880ef281c7b7b4cf9dabc + cmsLocaleId: 66f6e966c9e1dc700a857ca3 + lastPublished: '2023-04-15T10:25:18.123Z' + lastUpdated: '2023-04-10T11:45:30.567Z' + createdOn: '2023-04-10T11:45:30.567Z' + isArchived: false + isDraft: false + fieldData: + name: Product Manager + slug: product-manager + url: https://boards.greenhouse.io/webflow/jobs/31234567 + department: Product + pagination: + limit: 25 + offset: 0 + total: 2 + create-item-live: + path: /collections/{collection_id}/items/live + method: POST + auth: true + docs: > + Create live Item(s) in a Collection. The Item(s) will be published to + the live site. + + + + To create items across multiple locales, [please use this + endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + + + + Required scope | `CMS:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: Create Live Collection Item(s) + request: + body: ItemsCreateItemLiveRequest + content-type: application/json + response: + docs: Request was successful + type: root.CollectionItem + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - name: SingleItem + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + isArchived: false + isDraft: false + fieldData: + name: Pan Galactic Gargle Blaster Recipe + slug: pan-galactic-gargle-blaster + date: '2022-11-18T00:00:00.000Z' + featured: true + color: '#db4b68' + response: + body: + id: 42b720ef280c7a7a3be8cabe + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2022-11-29T16:22:43.159Z' + lastUpdated: '2022-11-17T17:19:43.282Z' + createdOn: '2022-11-17T17:11:57.148Z' + isArchived: false + isDraft: false + fieldData: + name: Pan Galactic Gargle Blaster Recipe + slug: pan-galactic-gargle-blaster + color: '#db4b68' + date: '2022-11-18T00:00:00.000Z' + featured: true + - name: MultipleItems + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - isArchived: false + isDraft: false + fieldData: + name: Senior Data Analyst + slug: senior-data-analyst + url: https://boards.greenhouse.io/webflow/jobs/26567701 + department: Data + - isArchived: false + isDraft: false + fieldData: + name: Product Manager + slug: product-manager + url: https://boards.greenhouse.io/webflow/jobs/31234567 + department: Product + response: + body: + id: 42b720ef280c7a7a3be8cabe + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2022-11-29T16:22:43.159Z' + lastUpdated: '2022-11-17T17:19:43.282Z' + createdOn: '2022-11-17T17:11:57.148Z' + isArchived: false + isDraft: false + fieldData: + name: Pan Galactic Gargle Blaster Recipe + slug: pan-galactic-gargle-blaster + color: '#db4b68' + date: '2022-11-18T00:00:00.000Z' + featured: true + delete-items-live: + path: /collections/{collection_id}/items/live + method: DELETE + auth: true + docs: > + Remove an item or multiple items (up to 100 items) from the live site. + Deleting published items will unpublish the items from the live site and + set them to draft. + + + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the + items are localized, items will be unpublished only in the primary + locale. + + + Required scope | `CMS:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: Delete Live Collection Items + request: + name: ItemsDeleteItemsLiveRequest + body: + properties: + items: optional> + content-type: application/json + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: {} + update-items-live: + path: /collections/{collection_id}/items/live + method: PATCH + auth: true + docs: > + Update a single live item or multiple live items (up to 100) in a + Collection + + + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the + items are localized, items will be updated only in the primary locale. + + + Required scope | `CMS:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: Update Live Collection Items + request: + name: ItemsUpdateItemsLiveRequest + body: + properties: + items: optional> + content-type: application/json + response: + docs: Request was successful + type: root.CollectionItemListNoPagination + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - name: LocalizedItems + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Ne Paniquez Pas + slug: ne-paniquez-pas + featured: false + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: No Entrar en Pánico + slug: no-entrar-en-panico + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Au Revoir et Merci pour Tous les Poissons + slug: au-revoir-et-merci + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: Hasta Luego y Gracias por Todo el Pescado + slug: hasta-luego-y-gracias + featured: false + response: + body: + items: + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: Ne Paniquez Pas + slug: ne-paniquez-pas + featured: false + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: No Entrar en Pánico + slug: no-entrar-en-panico + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: Au Revoir et Merci pour Tous les Poissons + slug: au-revoir-et-merci + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: Hasta Luego y Gracias por Todo el Pescado + slug: hasta-luego-y-gracias + featured: false + - name: MultipleItems + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 580e64008c9a982ac9b8b754 + isArchived: false + isDraft: false + fieldData: + name: Senior Data Analyst + slug: senior-data-analyst + url: https://boards.greenhouse.io/webflow/jobs/26567701 + department: Data + - id: 580e64008c9a982ac9b8b754 + isArchived: false + isDraft: false + fieldData: + name: Product Manager + slug: product-manager + url: https://boards.greenhouse.io/webflow/jobs/31234567 + department: Product + response: + body: + items: + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: Ne Paniquez Pas + slug: ne-paniquez-pas + featured: false + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: No Entrar en Pánico + slug: no-entrar-en-panico + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: Au Revoir et Merci pour Tous les Poissons + slug: au-revoir-et-merci + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: Hasta Luego y Gracias por Todo el Pescado + slug: hasta-luego-y-gracias + featured: false + - name: Multiple items updated across multiple locales + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Ne Paniquez Pas + slug: ne-paniquez-pas + featured: false + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: No Entrar en Pánico + slug: no-entrar-en-panico + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Au Revoir et Merci pour Tous les Poissons + slug: au-revoir-et-merci + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: Hasta Luego y Gracias por Todo el Pescado + slug: hasta-luego-y-gracias + featured: false + response: + body: + items: + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: Ne Paniquez Pas + slug: ne-paniquez-pas + featured: false + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: No Entrar en Pánico + slug: no-entrar-en-panico + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: Au Revoir et Merci pour Tous les Poissons + slug: au-revoir-et-merci + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: true + isDraft: true + fieldData: + name: Hasta Luego y Gracias por Todo el Pescado + slug: hasta-luego-y-gracias + featured: false + - name: Mulitple items updated in a single locale + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Ne Paniquez Pas + slug: ne-paniquez-pas + featured: false + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: No Entrar en Pánico + slug: no-entrar-en-panico + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + fieldData: + name: Au Revoir et Merci pour Tous les Poissons + slug: au-revoir-et-merci + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + fieldData: + name: Hasta Luego y Gracias por Todo el Pescado + slug: hasta-luego-y-gracias + featured: false + response: + body: + items: + - id: 62b720ef280c7a7a3be8cabe + cmsLocaleId: 66f6e966c9e1dc700a857ca3 + lastPublished: '2022-06-30T13:35:20.878Z' + lastUpdated: '2022-06-25T14:51:27.809Z' + createdOn: '2022-06-25T14:51:27.809Z' + isArchived: false + isDraft: false + fieldData: + name: Senior Data Analyst + slug: senior-data-analyst + url: https://boards.greenhouse.io/webflow/jobs/26567701 + department: Data + - id: 62c880ef281c7b7b4cf9dabc + cmsLocaleId: 66f6e966c9e1dc700a857ca3 + lastPublished: '2023-04-15T10:25:18.123Z' + lastUpdated: '2023-04-10T11:45:30.567Z' + createdOn: '2023-04-10T11:45:30.567Z' + isArchived: false + isDraft: false + fieldData: + name: Product Manager + slug: product-manager + url: https://boards.greenhouse.io/webflow/jobs/31234567 + department: Product + create-items: + path: /collections/{collection_id}/items/bulk + method: POST + auth: true + docs: > + Create an item or multiple items in a CMS Collection across multiple + corresponding locales. + + + **Notes:** + - This endpoint can create up to 100 items in a request. + - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. + + Required scope | `CMS:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: Create Collection Items + request: + name: CreateBulkCollectionItemRequestBody + body: + properties: + cmsLocaleIds: + type: optional> + docs: >- + Array of identifiers for the locales where the item will be + created + isArchived: + type: optional + docs: Indicates whether the item is archived. + default: false + isDraft: + type: optional + docs: Indicates whether the item is in draft state. + default: false + fieldData: CreateBulkCollectionItemRequestBodyFieldData + content-type: application/json + response: + docs: Request was successful + type: root.BulkCollectionItem + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - name: Create a single item across multiple locales + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + cmsLocaleIds: + - 66f6e966c9e1dc700a857ca3 + - 66f6e966c9e1dc700a857ca4 + - 66f6e966c9e1dc700a857ca5 + isArchived: false + isDraft: false + fieldData: + name: Don’t Panic + slug: dont-panic + response: + body: + id: 580e64008c9a982ac9b8b754 + cmsLocaleIds: + - 653ad57de882f528b32e810e + - 6514390aea353fc691d69827 + - 65143930ea353fc691d69cd8 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + isArchived: true + isDraft: true + fieldData: + name: My new item + slug: my-new-item + date: '2022-11-18T00:00:00.000Z' + featured: false + color: '#db4b68' + - name: Create multiple items across multipel locales + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + cmsLocaleIds: + - 66f6e966c9e1dc700a857ca3 + - 66f6e966c9e1dc700a857ca4 + isArchived: false + isDraft: false + fieldData: + - name: Don’t Panic + slug: dont-panic + - name: So Long and Thanks for All the Fish + slug: so-long-and-thanks + response: + body: + id: 580e64008c9a982ac9b8b754 + cmsLocaleIds: + - 653ad57de882f528b32e810e + - 6514390aea353fc691d69827 + - 65143930ea353fc691d69cd8 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + isArchived: true + isDraft: true + fieldData: + name: My new item + slug: my-new-item + date: '2022-11-18T00:00:00.000Z' + featured: false + color: '#db4b68' + - name: Single item created across multiple locales + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + cmsLocaleIds: + - 66f6e966c9e1dc700a857ca3 + - 66f6e966c9e1dc700a857ca4 + - 66f6e966c9e1dc700a857ca5 + isArchived: false + isDraft: false + fieldData: + name: Don’t Panic + slug: dont-panic + response: + body: + id: 580e64008c9a982ac9b8b754 + cmsLocaleIds: + - 653ad57de882f528b32e810e + - 6514390aea353fc691d69827 + - 65143930ea353fc691d69cd8 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + isArchived: true + isDraft: true + fieldData: + name: My new item + slug: my-new-item + date: '2022-11-18T00:00:00.000Z' + featured: false + color: '#db4b68' + - name: Multiple items created across multiple locales + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + cmsLocaleIds: + - 66f6e966c9e1dc700a857ca3 + - 66f6e966c9e1dc700a857ca4 + - 66f6e966c9e1dc700a857ca5 + isArchived: false + isDraft: false + fieldData: + name: Don’t Panic + slug: dont-panic + response: + body: + id: 580e64008c9a982ac9b8b754 + cmsLocaleIds: + - 653ad57de882f528b32e810e + - 6514390aea353fc691d69827 + - 65143930ea353fc691d69cd8 + lastPublished: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + createdOn: '2023-03-17T18:47:35.560Z' + isArchived: true + isDraft: true + fieldData: + name: My new item + slug: my-new-item + date: '2022-11-18T00:00:00.000Z' + featured: false + color: '#db4b68' + get-item: + path: /collections/{collection_id}/items/{item_id} + method: GET + auth: true + docs: | + Get details of a selected Collection Item. + + Required scope | `CMS:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + item_id: + type: string + docs: Unique identifier for an Item + display-name: Get Collection Item + request: + name: ItemsGetItemRequest + query-parameters: + cmsLocaleId: + type: optional + docs: >- + Unique identifier for a CMS Locale. This UID is different from the + Site locale identifier and is listed as `cmsLocaleId` in the Sites + response. To query multiple locales, input a comma separated + string. + response: + docs: Request was successful + type: root.CollectionItem + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + item_id: 580e64008c9a982ac9b8b754 + response: + body: + id: 42b720ef280c7a7a3be8cabe + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2022-11-29T16:22:43.159Z' + lastUpdated: '2022-11-17T17:19:43.282Z' + createdOn: '2022-11-17T17:11:57.148Z' + isArchived: false + isDraft: false + fieldData: + name: Pan Galactic Gargle Blaster Recipe + slug: pan-galactic-gargle-blaster + color: '#db4b68' + date: '2022-11-18T00:00:00.000Z' + featured: true + delete-item: + path: /collections/{collection_id}/items/{item_id} + method: DELETE + auth: true + docs: > + Delete an Item from a Collection. This endpoint does not currently + support bulk deletion. + + + Required scope | `CMS:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + item_id: + type: string + docs: Unique identifier for an Item + display-name: Delete Collection Item + request: + name: ItemsDeleteItemRequest + query-parameters: + cmsLocaleId: + type: optional + docs: >- + Unique identifier for a CMS Locale. This UID is different from the + Site locale identifier and is listed as `cmsLocaleId` in the Sites + response. To query multiple locales, input a comma separated + string. + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + item_id: 580e64008c9a982ac9b8b754 + update-item: + path: /collections/{collection_id}/items/{item_id} + method: PATCH + auth: true + docs: | + Update a selected Item in a Collection. + + Required scope | `CMS:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + item_id: + type: string + docs: Unique identifier for an Item + display-name: Update Collection Item + request: + body: root.CollectionItemPatchSingle + content-type: application/json + response: + docs: Request was successful + type: root.CollectionItem + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + item_id: 580e64008c9a982ac9b8b754 + request: + isArchived: false + isDraft: false + fieldData: + name: Pan Galactic Gargle Blaster Recipe + slug: pan-galactic-gargle-blaster + date: '2022-11-18T00:00:00.000Z' + featured: true + color: '#db4b68' + response: + body: + id: 42b720ef280c7a7a3be8cabe + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2022-11-29T16:22:43.159Z' + lastUpdated: '2022-11-17T17:19:43.282Z' + createdOn: '2022-11-17T17:11:57.148Z' + isArchived: false + isDraft: false + fieldData: + name: Pan Galactic Gargle Blaster Recipe + slug: pan-galactic-gargle-blaster + color: '#db4b68' + date: '2022-11-18T00:00:00.000Z' + featured: true + get-item-live: + path: /collections/{collection_id}/items/{item_id}/live + method: GET + auth: true + docs: | + Get details of a selected Collection live Item. + + Required scope | `CMS:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + item_id: + type: string + docs: Unique identifier for an Item + display-name: Get Live Collection Item + request: + name: ItemsGetItemLiveRequest + query-parameters: + cmsLocaleId: + type: optional + docs: >- + Unique identifier for a CMS Locale. This UID is different from the + Site locale identifier and is listed as `cmsLocaleId` in the Sites + response. To query multiple locales, input a comma separated + string. + response: + docs: Request was successful + type: root.CollectionItem + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + item_id: 580e64008c9a982ac9b8b754 + response: + body: + id: 42b720ef280c7a7a3be8cabe + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2022-11-29T16:22:43.159Z' + lastUpdated: '2022-11-17T17:19:43.282Z' + createdOn: '2022-11-17T17:11:57.148Z' + isArchived: false + isDraft: false + fieldData: + name: Pan Galactic Gargle Blaster Recipe + slug: pan-galactic-gargle-blaster + color: '#db4b68' + date: '2022-11-18T00:00:00.000Z' + featured: true + delete-item-live: + path: /collections/{collection_id}/items/{item_id}/live + method: DELETE + auth: true + docs: > + Remove a live item from the site. Removing a published item will + unpublish the item from the live site and set it to draft. + + + This endpoint does not currently support bulk deletion. + + + Required scope | `CMS:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + item_id: + type: string + docs: Unique identifier for an Item + display-name: Delete Live Collection Item + request: + name: ItemsDeleteItemLiveRequest + query-parameters: + cmsLocaleId: + type: optional + docs: >- + Unique identifier for a CMS Locale. This UID is different from the + Site locale identifier and is listed as `cmsLocaleId` in the Sites + response. To query multiple locales, input a comma separated + string. + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + item_id: 580e64008c9a982ac9b8b754 + update-item-live: + path: /collections/{collection_id}/items/{item_id}/live + method: PATCH + auth: true + docs: > + Update a selected live Item in a Collection. The updates for this Item + will be published to the live site. + + + Required scope | `CMS:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + item_id: + type: string + docs: Unique identifier for an Item + display-name: Update Live Collection Item + request: + body: root.CollectionItemPatchSingle + content-type: application/json + response: + docs: Request was successful + type: root.CollectionItem + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + item_id: 580e64008c9a982ac9b8b754 + request: + isArchived: false + isDraft: false + fieldData: + name: Pan Galactic Gargle Blaster Recipe + slug: pan-galactic-gargle-blaster + date: '2022-11-18T00:00:00.000Z' + featured: true + color: '#db4b68' + response: + body: + id: 42b720ef280c7a7a3be8cabe + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2022-11-29T16:22:43.159Z' + lastUpdated: '2022-11-17T17:19:43.282Z' + createdOn: '2022-11-17T17:11:57.148Z' + isArchived: false + isDraft: false + fieldData: + name: Pan Galactic Gargle Blaster Recipe + slug: pan-galactic-gargle-blaster + color: '#db4b68' + date: '2022-11-18T00:00:00.000Z' + featured: true + publish-item: + path: /collections/{collection_id}/items/publish + method: POST + auth: true + docs: | + Publish an item or multiple items. + + Required scope | `cms:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + display-name: Publish Collection Item + request: + name: ItemsPublishItemRequest + body: + properties: + itemIds: list + content-type: application/json + response: + docs: Request was successful + type: ItemsPublishItemResponse + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + itemIds: + - itemIds + response: + body: + publishedItemIds: + - 643fd856d66b6528195ee2ca + - 643fd856d66b6528195ee2cb + errors: + - Staging item ID 643fd856d66b6528195ee2cf not found. + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/components.yml b/.mock/definition/components.yml new file mode 100644 index 0000000..b9eb7d6 --- /dev/null +++ b/.mock/definition/components.yml @@ -0,0 +1,486 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/components + method: GET + auth: true + docs: | + List of all components for a site. + + Required scope | `components:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Components + request: + name: ComponentsListRequest + query-parameters: + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + response: + docs: Request was successful + type: root.ComponentList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + components: + - id: 6596da6045e56dee495bcbba + name: Primary Button + group: Buttons + description: A default button component that can be used across the site + readonly: true + - id: 658205daa3e8206a523b5ad4 + name: Secondary Button + group: Buttons + description: >- + A secondary button component that can be used across the + site + readonly: true + - id: 6258612d1ee792848f805dcf + name: Card + group: Buttons + description: A button component that can be used across the site + readonly: true + - id: 68a2b1d1ee792848f805dcf + name: Nav + group: Buttons + description: A button component that can be used across the site + readonly: true + pagination: + limit: 20 + offset: 0 + total: 4 + get-content: + path: /sites/{site_id}/components/{component_id}/dom + method: GET + auth: true + docs: > + Get static content from a component definition. This includes text + nodes, image nodes and nested component instances. + + To retrieve dynamic content set by component properties, use the [get + component + properties](/data/reference/pages-and-components/components/get-properties) + endpoint. + + + If you do not provide a Locale ID in your request, the response + will return any content that can be localized from the Primary + locale. + + + Required scope | `components:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + component_id: + type: string + docs: Unique identifier for a Component + display-name: Get Component Content + request: + name: ComponentsGetContentRequest + query-parameters: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + response: + docs: Request was successful + type: root.ComponentDom + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - name: ComponentDOM + path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + response: + body: + componentId: 69118560-d0bc-15fc-bbf8-b8fe5f6535b5 + nodes: + - type: component-instance + id: a245c12d-995b-55ee-5ec7-aa36a6cad623 + componentId: nodes + propertyOverrides: + - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 + - type: component-instance + id: a245c12d-995b-55ee-5ec7-aa36a6cad627 + componentId: nodes + propertyOverrides: + - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 + - type: component-instance + id: a245c12d-995b-55ee-5ec7-aa36a6cad629 + componentId: nodes + propertyOverrides: + - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 + - type: component-instance + id: a245c12d-995b-55ee-5ec7-aa36a6cad631 + componentId: 6258612d1ee792848f805dcf + propertyOverrides: + - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad633 + type: Plain Text + text: + text: Don't Panic! + - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad635 + type: Rich Text + text: + html:

Always know where your towel is.

+ pagination: + limit: 4 + offset: 0 + total: 4 + - name: LocalizedComponentDOM + path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + response: + body: + componentId: 69118560-d0bc-15fc-bbf8-b8fe5f6535b5 + nodes: + - type: component-instance + id: 69118560-d0bc-15fc-bbf8-b8fe5f6535b8 + componentId: nodes + propertyOverrides: + - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 + - type: component-instance + id: 8ebfb409-7493-3bca-5d48-0e547befb960 + componentId: nodes + propertyOverrides: + - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 + - type: component-instance + id: 69118560-d0bc-15fc-bbf8-b8fe5f6535c2 + componentId: 69118560-d0bc-15fc-bbf8-b8fe5f6535b5 + propertyOverrides: + - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad623 + pagination: + limit: 100 + offset: 0 + total: 3 + update-content: + path: /sites/{site_id}/components/{component_id}/dom + method: POST + auth: true + docs: > + This endpoint updates content within a component defintion for + **secondary locales**. It supports updating up to 1000 nodes in a single + request. + + + Before making updates: + + 1. Use the [get component + content](/data/reference/pages-and-components/components/get-content) + endpoint to identify available content nodes and their types + + 2. If your component definition has a component instance nested within + it, retrieve the nested component instance's properties that you'll + override using the [get component + properties](/data/reference/pages-and-components/components/get-properties) + endpoint + + + + This endpoint is specifically for localizing component definitions. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + + + Required scope | `components:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + component_id: + type: string + docs: Unique identifier for a Component + display-name: Update Component Content + request: + name: ComponentDomWrite + query-parameters: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + body: + properties: + nodes: + docs: >- + List of DOM Nodes with the new content that will be updated in + each node. + type: list + content-type: application/json + response: + docs: Request was successful + type: ComponentsUpdateContentResponse + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + request: + nodes: + - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad623 + text:

The Hitchhiker's Guide to the Galaxy

+ - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad627 + text: >- +

Don't Panic!

Always know where your towel + is.

+ - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad629 + propertyOverrides: + - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 + text:

Time is an illusion

+ - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f1 + text: Life, the Universe and Everything + response: + body: + errors: + - errors + get-properties: + path: /sites/{site_id}/components/{component_id}/properties + method: GET + auth: true + docs: > + Get the property default values of a component definition. + + + If you do not provide a Locale ID in your request, the response + will return any properties that can be localized from the Primary + locale. + + + Required scope | `components:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + component_id: + type: string + docs: Unique identifier for a Component + display-name: Get Component Properties + request: + name: ComponentsGetPropertiesRequest + query-parameters: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + response: + docs: Request was successful + type: root.ComponentProperties + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + response: + body: + componentId: 658205daa3e8206a523b5ad4 + properties: + - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad623 + type: Plain Text + label: Title + text: + text: The Hitchhiker's Guide to the Galaxy + - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad627 + type: Rich Text + label: Content + text: + html: >- +

Don't Panic!

Always know where your towel + is.

+ pagination: + limit: 2 + offset: 0 + total: 2 + update-properties: + path: /sites/{site_id}/components/{component_id}/properties + method: POST + auth: true + docs: > + Update the property default values of a component definition in a + specificed locale. + + + Before making updates: + + 1. Use the [get component + properties](/data/reference/pages-and-components/components/get-properties) + endpoint to identify available properties + + + The request requires a secondary locale ID. If a locale is + missing, the request will not be processed and will result in an + error. + + + Required scope | `components:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + component_id: + type: string + docs: Unique identifier for a Component + display-name: Update Component Properties + request: + name: ComponentPropertiesWrite + query-parameters: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + body: + properties: + properties: + docs: >- + A list of component properties to update within the specified + secondary locale. + type: list + content-type: application/json + response: + docs: Request was successful + type: ComponentsUpdatePropertiesResponse + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + request: + properties: + - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad623 + text: The Hitchhiker’s Guide to the Galaxy + - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad627 + text: >- +

Dont Panic!

Always know where your towel + is.

+ response: + body: + errors: + - errors + source: + openapi: ../../../openapi/referenced-specs/v2.yml +types: + ComponentDomWriteNodesItem: + discriminated: false + union: + - root.TextNodeWrite + - root.ComponentInstanceNodePropertyOverridesWrite + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ComponentsUpdateContentResponse: + properties: + errors: + docs: A list of error messages, if any. + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ComponentPropertiesWritePropertiesItem: + properties: + propertyId: + type: string + docs: The ID of the property. + text: + type: string + docs: > + The new string or HTML value used to update the component property in + the secondary locale. + + + The provided value must be compatible with the type of the component + property. + + + For example, attempting to update a single-line plain-text property + with a multi-line + + value will result in an error. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ComponentsUpdatePropertiesResponse: + properties: + errors: + docs: A list of error messages, if any. + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/ecommerce.yml b/.mock/definition/ecommerce.yml new file mode 100644 index 0000000..1a2ca95 --- /dev/null +++ b/.mock/definition/ecommerce.yml @@ -0,0 +1,42 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + get-settings: + path: /sites/{site_id}/ecommerce/settings + method: GET + auth: true + docs: | + Retrieve ecommerce settings for a site. + + Required scope | `ecommerce:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Get Ecommerce Settings + response: + docs: Request was successful + type: root.EcommerceSettings + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + siteId: 5eb0b5583bf24e2d3a488969 + createdOn: '2018-10-04T15:21:02Z' + defaultCurrency: USD + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/forms.yml b/.mock/definition/forms.yml new file mode 100644 index 0000000..9eac177 --- /dev/null +++ b/.mock/definition/forms.yml @@ -0,0 +1,302 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/forms + method: GET + auth: true + docs: | + List forms for a given site. + + Required scope | `forms:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Forms + request: + name: FormsListRequest + query-parameters: + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + response: + docs: Request was successful + type: root.FormList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + forms: + - displayName: Email Form + createdOn: '2016-10-24T19:41:29Z' + lastUpdated: '2016-10-24T19:43:17Z' + fields: + '0': + displayName: Email + userVisible: true + '1': + displayName: Email + userVisible: true + responseSettings: + redirectUrl: https://example.com + redirectMethod: GET + sendEmailConfirmation: true + id: 589a331aa51e760df7ccb89e + siteId: 580e63e98c9a982ac9b8b741 + siteDomainId: 6419db964a9c436a4baf6248 + pageId: 6419db964a9c43f6a3af6348 + pageName: Home + formElementId: 4e038d2c-6a1e-4953-7be9-a59a2b453177 + workspaceId: 580e63fc8c9a982ac9b8b744 + - displayName: Name Form + createdOn: '2016-10-24T19:41:29Z' + lastUpdated: '2016-10-24T19:43:17Z' + fields: + '0': + displayName: Email + userVisible: true + responseSettings: + redirectUrl: https://example.com + redirectMethod: GET + sendEmailConfirmation: false + id: 580ff8d7ba3e45ba9fe588e9 + siteId: 580e63e98c9a982ac9b8b741 + siteDomainId: 6419db964a9c436a4baf6248 + pageId: 6419db964a9c43f6a3af6348 + pageName: Home + formElementId: 4e038d2c-6a1e-4953-7be9-a59a2b453177 + workspaceId: 580e63fc8c9a982ac9b8b744 + pagination: + limit: 25 + offset: 0 + total: 2 + get: + path: /forms/{form_id} + method: GET + auth: true + docs: | + Get information about a given form. + + Required scope | `forms:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + form_id: + type: string + docs: Unique identifier for a Form + display-name: Get Form Schema + response: + docs: Request was successful + type: root.Form + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + form_id: 580e63e98c9a982ac9b8b741 + response: + body: + displayName: Email Form + createdOn: '2016-10-24T19:41:29Z' + lastUpdated: '2016-10-24T19:43:17Z' + fields: + 660d5bcc9c0772150459dfb1: + displayName: Name + type: Plain + placeholder: Enter your email + userVisible: true + 589a331aa51e760df7ccb89d: + displayName: Email + type: Email + placeholder: Enter your email + userVisible: true + responseSettings: + redirectUrl: https://example.com + redirectMethod: GET + redirectAction: POST https://example.com + sendEmailConfirmation: true + id: 589a331aa51e760df7ccb89e + siteId: 580e63e98c9a982ac9b8b741 + siteDomainId: 6419db964a9c436a4baf6248 + pageId: 6419db964a9c43f6a3af6348 + pageName: Home + formElementId: 4e038d2c-6a1e-4953-7be9-a59a2b453177 + workspaceId: 580e63fc8c9a982ac9b8b744 + list-submissions: + path: /forms/{form_id}/submissions + method: GET + auth: true + docs: | + List form submissions for a given form + + Required scope | `forms:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + form_id: + type: string + docs: Unique identifier for a Form + display-name: List Form Submissions + request: + name: FormsListSubmissionsRequest + query-parameters: + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + response: + docs: Request was successful + type: root.FormSubmissionList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + form_id: 580e63e98c9a982ac9b8b741 + response: + body: + formSubmissions: + - id: 6321ca84df3949bfc6752327 + displayName: Sample Form + siteId: 62749158efef318abc8d5a0f + workspaceId: 62749158efef318abc8d5a0f + dateSubmitted: '2022-09-14T12:35:16Z' + formResponse: + First Name: Arthur + Last Name: Dent + - id: 660d64fabf6e0a0d4edab981 + displayName: Sample Form + siteId: 62749158efef318abc8d5a0f + workspaceId: 62749158efef318abc8d5a0f + dateSubmitted: '2022-09-14T12:35:16Z' + formResponse: + First Name: Ford + Last Name: Prefect + pagination: + limit: 25 + offset: 0 + total: 2 + get-submission: + path: /form_submissions/{form_submission_id} + method: GET + auth: true + docs: | + Get information about a given form submissio. + + Required scope | `forms:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + form_submission_id: + type: string + docs: Unique identifier for a Form Submission + display-name: Get Form Submission + response: + docs: Request was successful + type: root.FormSubmission + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + form_submission_id: 580e63e98c9a982ac9b8b741 + response: + body: + id: 6321ca84df3949bfc6752327 + displayName: Sample Form + siteId: 62749158efef318abc8d5a0f + workspaceId: 62749158efef318abc8d5a0f + dateSubmitted: '2022-09-14T12:35:16Z' + formResponse: + First Name: Arthur + Last Name: Dent + update-submission: + path: /form_submissions/{form_submission_id} + method: PATCH + auth: true + docs: | + Update hidden fields on a form submission + + Required scope | `forms:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + form_submission_id: + type: string + docs: Unique identifier for a Form Submission + display-name: Modify Form Submission + request: + name: FormsUpdateSubmissionRequest + body: + properties: + formSubmissionData: + type: optional> + docs: >- + An existing **hidden field** defined on the form schema, and the + corresponding value to set + content-type: application/json + response: + docs: Request was successful + type: root.FormSubmission + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + form_submission_id: 580e63e98c9a982ac9b8b741 + request: {} + response: + body: + id: 6321ca84df3949bfc6752327 + displayName: Sample Form + siteId: 62749158efef318abc8d5a0f + workspaceId: 62749158efef318abc8d5a0f + dateSubmitted: '2022-09-14T12:35:16Z' + formResponse: + First Name: Arthur + Last Name: Dent + source: + openapi: ../../../openapi/referenced-specs/v2.yml + display-name: Forms +docs: Forms are forms that are created on your Webflow site. diff --git a/.mock/definition/inventory.yml b/.mock/definition/inventory.yml new file mode 100644 index 0000000..5e69c29 --- /dev/null +++ b/.mock/definition/inventory.yml @@ -0,0 +1,122 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /collections/{collection_id}/items/{item_id}/inventory + method: GET + auth: true + docs: | + List the current inventory levels for a particular SKU item. + + Required scope | `ecommerce:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + item_id: + type: string + docs: Unique identifier for an Item + display-name: List Inventory + response: + docs: Request was successful + type: root.InventoryItem + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + item_id: 580e64008c9a982ac9b8b754 + response: + body: + id: 5bfedb42bab0ad90fa7dad39 + quantity: 100 + inventoryType: finite + update: + path: /collections/{collection_id}/items/{item_id}/inventory + method: PATCH + auth: true + docs: > + Updates the current inventory levels for a particular SKU item. + + + Updates may be given in one or two methods, absolutely or + incrementally. + + - Absolute updates are done by setting `quantity` directly. + + - Incremental updates are by specifying the inventory delta in + `updateQuantity` which is then added to the `quantity` stored on the + server. + + + Required scope | `ecommerce:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + collection_id: + type: string + docs: Unique identifier for a Collection + item_id: + type: string + docs: Unique identifier for an Item + display-name: Update Item Inventory + request: + name: InventoryUpdateRequest + body: + properties: + inventoryType: + type: InventoryUpdateRequestInventoryType + docs: infinite or finite + updateQuantity: + type: optional + docs: Adds this quantity to currently store quantity. Can be negative. + quantity: + type: optional + docs: Immediately sets quantity to this value. + content-type: application/json + response: + docs: Request was successful + type: root.InventoryItem + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + item_id: 580e64008c9a982ac9b8b754 + request: + inventoryType: infinite + response: + body: + id: 5bfedb42bab0ad90fa7dad39 + quantity: 100 + inventoryType: finite + source: + openapi: ../../../openapi/referenced-specs/v2.yml + display-name: Inventory +docs: Inventory is the stock of e-commerce items in your Webflow site. +types: + InventoryUpdateRequestInventoryType: + enum: + - infinite + - finite + docs: infinite or finite + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/orders.yml b/.mock/definition/orders.yml new file mode 100644 index 0000000..b2802cf --- /dev/null +++ b/.mock/definition/orders.yml @@ -0,0 +1,1571 @@ +types: + OrdersListRequestStatus: + enum: + - pending + - refunded + - value: dispute-lost + name: DisputeLost + - fulfilled + - disputed + - unfulfilled + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrdersRefundRequestReason: + enum: + - duplicate + - fraudulent + - requested + docs: The reason for the refund + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/orders + method: GET + auth: true + docs: | + List all orders created for a given site. + + Required scope | `ecommerce:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Orders + request: + name: OrdersListRequest + query-parameters: + status: + type: optional + docs: Filter the orders by status + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + response: + docs: Request was successful + type: root.OrderList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + orders: + - orderId: 7c1-9fd + status: unfulfilled + comment: >- + Customer requested gift wrapping and a personalized note + saying: Happy Birthday, Ford! 🎉 Please ensure the item is + packed with extra bubble wrap for safe transit. + orderComment: >- + Please gift wrap with a personal note saying "Happy + Birthday, Ford! 🎉 + acceptedOn: '2024-04-10T13:16:21Z' + fulfilledOn: '2018-12-03T22:06:15Z' + refundedOn: '2018-12-03T22:06:15Z' + disputedOn: '2018-12-03T22:06:15Z' + disputeUpdatedOn: '2018-12-03T22:06:15Z' + disputeLastStatus: warning_needs_response + customerPaid: + unit: USD + value: '5892' + string: ' 211.55 USD' + netAmount: + unit: USD + value: '5892' + string: ' 200.89 USD' + applicationFee: + unit: USD + value: '5892' + string: ' 4.23 USD' + allAddresses: + - type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + - type: shipping + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingAddress: + type: shipping + japanType: kanji + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + billingAddress: + type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingProvider: Shipping Company, Co. + shippingTracking: tr00000000002 + shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000002 + customerInfo: + fullName: Arthur Dent + email: arthur.dent@example.com + purchasedItems: + - count: 2 + rowTotal: + unit: USD + value: '5892' + string: ' 111.22 USD' + productId: 66072fb61b89448912e26791 + productName: Luxurious Fresh Ball + productSlug: luxurious-fresh-ball + variantId: 66072fb71b89448912e2683f + variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' + variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic + variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 55.61 USD' + weight: 11 + width: 82 + height: 70 + length: 9 + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 83.09 USD' + productId: 66072fb61b89448912e2678b + productName: Incredible Bronze Towels + productSlug: incredible-bronze-towels + variantId: 66072fb71b89448912e2681e + variantName: >- + Incredible Bronze Towels Sleek: Frozen, Incredible: + Metal + variantSlug: incredible-bronze-towels-sleek-frozen-incredible-metal + variantSKU: incredible-bronze-towels-sleek-frozen-incredible-metal + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 83.09 USD' + width: 19 + height: 72 + length: 18 + purchasedItemsCount: 3 + stripeDetails: + paymentMethod: pm_1P410gJYFi4lcbXWbeKghqjK + paymentIntentId: pi_3P410iJYFi4lcbXW0EKKgcVg + customerId: cus_Ptod8KJBiiPgnH + chargeId: ch_3P410iJYFi4lcbXW0DxUkzCH + stripeCard: + last4: '4242' + brand: Visa + ownerName: Arthur Dent + expires: + year: 2025 + month: 4 + paypalDetails: + orderId: 1a2b3c4d5e6f7g8h9i0j + payerId: 9k8j7i6h5g4f3e2d1c0b + captureId: qwe123rty456uio789p + refundId: abcde12345fghij67890 + refundReason: Customer requested refund + disputeId: zxcvbnm987poiuytrewq + customData: + - key: value + metadata: + isBuyNow: false + isCustomerDeleted: false + isShippingRequired: false + hasDownloads: false + paymentProcessor: stripe + totals: + extras: + - type: tax + name: State Taxes + description: CA Taxes (6.25%) + price: + unit: USD + value: '5892' + string: '3.44' + downloadFiles: + - id: 5e9a5eba75e0ac242e1b6f64 + name: The modern web design process - Webflow Ebook.pdf + url: >- + https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa + - orderId: fc7-128 + status: refunded + comment: Example comment to myself + orderComment: '' + acceptedOn: '2024-03-29T21:29:21Z' + fulfilledOn: '2018-12-03T22:06:15Z' + refundedOn: '2024-04-08T18:25:04Z' + disputedOn: '2018-12-03T22:06:15Z' + disputeUpdatedOn: '2018-12-03T22:06:15Z' + disputeLastStatus: warning_needs_response + customerPaid: + unit: USD + value: '5892' + string: ' 118.73 USD' + netAmount: + unit: USD + value: '5892' + string: ' 112.62 USD' + applicationFee: + unit: USD + value: '5892' + string: ' 2.37 USD' + allAddresses: + - type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + - type: shipping + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingAddress: + type: shipping + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + billingAddress: + type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingProvider: Shipping Company, Co. + shippingTracking: tr00000000001 + shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 + customerInfo: + fullName: Arthur Dent + email: arthur.dent@example.com + purchasedItems: + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 55.61 USD' + productId: 66072fb61b89448912e26791 + productName: Luxurious Fresh Ball + productSlug: luxurious-fresh-ball + variantId: 66072fb71b89448912e2683f + variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' + variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic + variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 55.61 USD' + weight: 11 + width: 82 + height: 70 + length: 9 + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 53.44 USD' + productId: 66072fb61b89448912e26799 + productName: Recycled Steel Gloves + productSlug: recycled-steel-gloves + variantId: 66072fb91b89448912e26ab9 + variantName: >- + Recycled Steel Gloves Electronic: Granite, Handcrafted: + grey + variantSlug: >- + recycled-steel-gloves-electronic-granite-handcrafted-grey + variantSKU: >- + recycled-steel-gloves-electronic-granite-handcrafted-grey + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 53.44 USD' + weight: 38 + width: 76 + height: 85 + length: 40 + purchasedItemsCount: 2 + stripeDetails: + paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j + paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft + customerId: cus_PpRsNHwWdUoRKR + chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 + refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk + refundReason: fraudulent + stripeCard: + last4: '4242' + brand: Visa + ownerName: Arthur Dent + expires: + year: 2024 + month: 4 + paypalDetails: + orderId: 1a2b3c4d5e6f7g8h9i0j + payerId: 9k8j7i6h5g4f3e2d1c0b + captureId: qwe123rty456uio789p + refundId: abcde12345fghij67890 + refundReason: Customer requested refund + disputeId: zxcvbnm987poiuytrewq + customData: + - key: value + metadata: + isBuyNow: false + isCustomerDeleted: false + isShippingRequired: true + hasDownloads: false + paymentProcessor: stripe + totals: + subtotal: + unit: USD + value: '5892' + string: ' 109.05 USD' + extras: + - type: tax + name: State Taxes + description: NY Taxes (4.00%) + price: + unit: USD + value: '5892' + string: ' 4.36 USD' + - type: tax + name: City Taxes + description: NEW YORK Taxes (4.88%) + price: + unit: USD + value: '5892' + string: ' 5.32 USD' + - type: shipping + name: Flat + description: '' + price: + unit: USD + value: '5892' + string: ' 0.00 USD' + total: + unit: USD + value: '5892' + string: ' 118.73 USD' + downloadFiles: + - id: 5e9a5eba75e0ac242e1b6f64 + name: New product guide + url: >- + https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa + pagination: + limit: 100 + offset: 0 + total: 2 + get: + path: /sites/{site_id}/orders/{order_id} + method: GET + auth: true + docs: | + Retrieve a single product by its ID. All of its SKUs will also be + retrieved. + + Required scope | `ecommerce:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + order_id: + type: string + docs: Unique identifier for an Order + display-name: Get Order + response: + docs: Request was successful + type: root.Order + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + order_id: 5e8518516e147040726cc415 + response: + body: + orderId: fc7-128 + status: refunded + comment: >- + Customer requested gift wrapping and a personalized note saying: + Happy Birthday, Ford! 🎉 Please ensure the item is packed with + extra bubble wrap for safe transit. + orderComment: >- + Please gift wrap with a personal note saying "Happy Birthday, + Ford! 🎉 + acceptedOn: '2024-03-29T21:29:21Z' + fulfilledOn: '2024-03-29T21:29:21Z' + refundedOn: '2024-04-08T18:25:04Z' + disputedOn: '2024-03-29T21:29:21Z' + disputeUpdatedOn: '2024-03-29T21:29:21Z' + disputeLastStatus: charge_refunded + customerPaid: + unit: USD + value: '5892' + string: ' 118.73 USD' + netAmount: + unit: USD + value: '5892' + string: ' 112.62 USD' + applicationFee: + unit: USD + value: '5892' + string: ' 2.37 USD' + allAddresses: + - type: billing + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + - type: shipping + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingAddress: + type: shipping + japanType: kanji + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + billingAddress: + type: billing + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingProvider: Shipping Company, Co. + shippingTracking: tr00000000001 + shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 + customerInfo: + fullName: Arthur Dent + email: arthur.dent@example.com + purchasedItems: + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 55.61 USD' + productId: 66072fb61b89448912e26791 + productName: Luxurious Fresh Ball + productSlug: luxurious-fresh-ball + variantId: 66072fb71b89448912e2683f + variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' + variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic + variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 55.61 USD' + weight: 11 + width: 82 + height: 70 + length: 9 + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 53.44 USD' + productId: 66072fb61b89448912e26799 + productName: Recycled Steel Gloves + productSlug: recycled-steel-gloves + variantId: 66072fb91b89448912e26ab9 + variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' + variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 53.44 USD' + weight: 38 + width: 76 + height: 85 + length: 40 + purchasedItemsCount: 2 + stripeDetails: + subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn + paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j + paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft + customerId: cus_PpRsNHwWdUoRKR + chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 + disputeId: disputeId + refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk + refundReason: fraudulent + stripeCard: + last4: '4242' + brand: Visa + ownerName: Arthur Dent + expires: + year: 2024 + month: 4 + paypalDetails: + orderId: 1a2b3c4d5e6f7g8h9i0j + payerId: 9k8j7i6h5g4f3e2d1c0b + captureId: qwe123rty456uio789p + refundId: abcde12345fghij67890 + refundReason: Customer requested refund + disputeId: zxcvbnm987poiuytrewq + customData: + - key: value + metadata: + isBuyNow: false + isCustomerDeleted: false + isShippingRequired: true + hasDownloads: false + paymentProcessor: stripe + totals: + subtotal: + unit: USD + value: '5892' + string: ' 109.05 USD' + extras: + - type: tax + name: State Taxes + description: NY Taxes (4.00%) + price: + unit: USD + value: '5892' + string: ' 4.36 USD' + - type: tax + name: City Taxes + description: NEW YORK Taxes (4.88%) + price: + unit: USD + value: '5892' + string: ' 5.32 USD' + - type: shipping + name: Flat + description: '' + price: + unit: USD + value: '5892' + string: ' 0.00 USD' + total: + unit: USD + value: '5892' + string: ' 118.73 USD' + downloadFiles: + - id: 5e9a5eba75e0ac242e1b6f64 + name: New product guide + url: >- + https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa + update: + path: /sites/{site_id}/orders/{order_id} + method: PATCH + auth: true + docs: | + This API lets you update the fields, `comment`, `shippingProvider`, + and/or `shippingTracking` for a given order. All three fields can be + updated simultaneously or independently. + + Required scope | `ecommerce:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + order_id: + type: string + docs: Unique identifier for an Order + display-name: Update Order + request: + name: OrdersUpdateRequest + body: + properties: + comment: + type: optional + docs: Arbitrary data for your records + shippingProvider: + type: optional + docs: Company or method used to ship order + shippingTracking: + type: optional + docs: Tracking number for order shipment + shippingTrackingURL: + type: optional + docs: URL to track order shipment + content-type: application/json + response: + docs: Request was successful + type: root.Order + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + order_id: 5e8518516e147040726cc415 + request: {} + response: + body: + orderId: fc7-128 + status: refunded + comment: >- + Customer requested gift wrapping and a personalized note saying: + Happy Birthday, Ford! 🎉 Please ensure the item is packed with + extra bubble wrap for safe transit. + orderComment: >- + Please gift wrap with a personal note saying "Happy Birthday, + Ford! 🎉 + acceptedOn: '2024-03-29T21:29:21Z' + fulfilledOn: '2024-03-29T21:29:21Z' + refundedOn: '2024-04-08T18:25:04Z' + disputedOn: '2024-03-29T21:29:21Z' + disputeUpdatedOn: '2024-03-29T21:29:21Z' + disputeLastStatus: charge_refunded + customerPaid: + unit: USD + value: '5892' + string: ' 118.73 USD' + netAmount: + unit: USD + value: '5892' + string: ' 112.62 USD' + applicationFee: + unit: USD + value: '5892' + string: ' 2.37 USD' + allAddresses: + - type: billing + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + - type: shipping + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingAddress: + type: shipping + japanType: kanji + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + billingAddress: + type: billing + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingProvider: Shipping Company, Co. + shippingTracking: tr00000000001 + shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 + customerInfo: + fullName: Arthur Dent + email: arthur.dent@example.com + purchasedItems: + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 55.61 USD' + productId: 66072fb61b89448912e26791 + productName: Luxurious Fresh Ball + productSlug: luxurious-fresh-ball + variantId: 66072fb71b89448912e2683f + variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' + variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic + variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 55.61 USD' + weight: 11 + width: 82 + height: 70 + length: 9 + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 53.44 USD' + productId: 66072fb61b89448912e26799 + productName: Recycled Steel Gloves + productSlug: recycled-steel-gloves + variantId: 66072fb91b89448912e26ab9 + variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' + variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 53.44 USD' + weight: 38 + width: 76 + height: 85 + length: 40 + purchasedItemsCount: 2 + stripeDetails: + subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn + paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j + paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft + customerId: cus_PpRsNHwWdUoRKR + chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 + disputeId: disputeId + refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk + refundReason: fraudulent + stripeCard: + last4: '4242' + brand: Visa + ownerName: Arthur Dent + expires: + year: 2024 + month: 4 + paypalDetails: + orderId: 1a2b3c4d5e6f7g8h9i0j + payerId: 9k8j7i6h5g4f3e2d1c0b + captureId: qwe123rty456uio789p + refundId: abcde12345fghij67890 + refundReason: Customer requested refund + disputeId: zxcvbnm987poiuytrewq + customData: + - key: value + metadata: + isBuyNow: false + isCustomerDeleted: false + isShippingRequired: true + hasDownloads: false + paymentProcessor: stripe + totals: + subtotal: + unit: USD + value: '5892' + string: ' 109.05 USD' + extras: + - type: tax + name: State Taxes + description: NY Taxes (4.00%) + price: + unit: USD + value: '5892' + string: ' 4.36 USD' + - type: tax + name: City Taxes + description: NEW YORK Taxes (4.88%) + price: + unit: USD + value: '5892' + string: ' 5.32 USD' + - type: shipping + name: Flat + description: '' + price: + unit: USD + value: '5892' + string: ' 0.00 USD' + total: + unit: USD + value: '5892' + string: ' 118.73 USD' + downloadFiles: + - id: 5e9a5eba75e0ac242e1b6f64 + name: New product guide + url: >- + https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa + update-fulfill: + path: /sites/{site_id}/orders/{order_id}/fulfill + method: POST + auth: true + docs: | + Updates an order's status to fulfilled + + Required scope | `ecommerce:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + order_id: + type: string + docs: Unique identifier for an Order + display-name: Fulfill Order + request: + name: OrdersUpdateFulfillRequest + body: + properties: + sendOrderFulfilledEmail: + type: optional + docs: Whether or not the Order Fulfilled email should be sent + default: false + content-type: application/json + response: + docs: Request was successful + type: root.Order + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + order_id: 5e8518516e147040726cc415 + request: {} + response: + body: + orderId: fc7-128 + status: refunded + comment: >- + Customer requested gift wrapping and a personalized note saying: + Happy Birthday, Ford! 🎉 Please ensure the item is packed with + extra bubble wrap for safe transit. + orderComment: >- + Please gift wrap with a personal note saying "Happy Birthday, + Ford! 🎉 + acceptedOn: '2024-03-29T21:29:21Z' + fulfilledOn: '2024-03-29T21:29:21Z' + refundedOn: '2024-04-08T18:25:04Z' + disputedOn: '2024-03-29T21:29:21Z' + disputeUpdatedOn: '2024-03-29T21:29:21Z' + disputeLastStatus: charge_refunded + customerPaid: + unit: USD + value: '5892' + string: ' 118.73 USD' + netAmount: + unit: USD + value: '5892' + string: ' 112.62 USD' + applicationFee: + unit: USD + value: '5892' + string: ' 2.37 USD' + allAddresses: + - type: billing + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + - type: shipping + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingAddress: + type: shipping + japanType: kanji + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + billingAddress: + type: billing + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingProvider: Shipping Company, Co. + shippingTracking: tr00000000001 + shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 + customerInfo: + fullName: Arthur Dent + email: arthur.dent@example.com + purchasedItems: + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 55.61 USD' + productId: 66072fb61b89448912e26791 + productName: Luxurious Fresh Ball + productSlug: luxurious-fresh-ball + variantId: 66072fb71b89448912e2683f + variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' + variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic + variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 55.61 USD' + weight: 11 + width: 82 + height: 70 + length: 9 + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 53.44 USD' + productId: 66072fb61b89448912e26799 + productName: Recycled Steel Gloves + productSlug: recycled-steel-gloves + variantId: 66072fb91b89448912e26ab9 + variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' + variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 53.44 USD' + weight: 38 + width: 76 + height: 85 + length: 40 + purchasedItemsCount: 2 + stripeDetails: + subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn + paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j + paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft + customerId: cus_PpRsNHwWdUoRKR + chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 + disputeId: disputeId + refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk + refundReason: fraudulent + stripeCard: + last4: '4242' + brand: Visa + ownerName: Arthur Dent + expires: + year: 2024 + month: 4 + paypalDetails: + orderId: 1a2b3c4d5e6f7g8h9i0j + payerId: 9k8j7i6h5g4f3e2d1c0b + captureId: qwe123rty456uio789p + refundId: abcde12345fghij67890 + refundReason: Customer requested refund + disputeId: zxcvbnm987poiuytrewq + customData: + - key: value + metadata: + isBuyNow: false + isCustomerDeleted: false + isShippingRequired: true + hasDownloads: false + paymentProcessor: stripe + totals: + subtotal: + unit: USD + value: '5892' + string: ' 109.05 USD' + extras: + - type: tax + name: State Taxes + description: NY Taxes (4.00%) + price: + unit: USD + value: '5892' + string: ' 4.36 USD' + - type: tax + name: City Taxes + description: NEW YORK Taxes (4.88%) + price: + unit: USD + value: '5892' + string: ' 5.32 USD' + - type: shipping + name: Flat + description: '' + price: + unit: USD + value: '5892' + string: ' 0.00 USD' + total: + unit: USD + value: '5892' + string: ' 118.73 USD' + downloadFiles: + - id: 5e9a5eba75e0ac242e1b6f64 + name: New product guide + url: >- + https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa + update-unfulfill: + path: /sites/{site_id}/orders/{order_id}/unfulfill + method: POST + auth: true + docs: | + Updates an order's status to unfulfilled + + Required scope | `ecommerce:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + order_id: + type: string + docs: Unique identifier for an Order + display-name: Unfulfill Order + response: + docs: Request was successful + type: root.Order + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + order_id: 5e8518516e147040726cc415 + response: + body: + orderId: fc7-128 + status: refunded + comment: >- + Customer requested gift wrapping and a personalized note saying: + Happy Birthday, Ford! 🎉 Please ensure the item is packed with + extra bubble wrap for safe transit. + orderComment: >- + Please gift wrap with a personal note saying "Happy Birthday, + Ford! 🎉 + acceptedOn: '2024-03-29T21:29:21Z' + fulfilledOn: '2024-03-29T21:29:21Z' + refundedOn: '2024-04-08T18:25:04Z' + disputedOn: '2024-03-29T21:29:21Z' + disputeUpdatedOn: '2024-03-29T21:29:21Z' + disputeLastStatus: charge_refunded + customerPaid: + unit: USD + value: '5892' + string: ' 118.73 USD' + netAmount: + unit: USD + value: '5892' + string: ' 112.62 USD' + applicationFee: + unit: USD + value: '5892' + string: ' 2.37 USD' + allAddresses: + - type: billing + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + - type: shipping + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingAddress: + type: shipping + japanType: kanji + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + billingAddress: + type: billing + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingProvider: Shipping Company, Co. + shippingTracking: tr00000000001 + shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 + customerInfo: + fullName: Arthur Dent + email: arthur.dent@example.com + purchasedItems: + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 55.61 USD' + productId: 66072fb61b89448912e26791 + productName: Luxurious Fresh Ball + productSlug: luxurious-fresh-ball + variantId: 66072fb71b89448912e2683f + variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' + variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic + variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 55.61 USD' + weight: 11 + width: 82 + height: 70 + length: 9 + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 53.44 USD' + productId: 66072fb61b89448912e26799 + productName: Recycled Steel Gloves + productSlug: recycled-steel-gloves + variantId: 66072fb91b89448912e26ab9 + variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' + variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 53.44 USD' + weight: 38 + width: 76 + height: 85 + length: 40 + purchasedItemsCount: 2 + stripeDetails: + subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn + paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j + paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft + customerId: cus_PpRsNHwWdUoRKR + chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 + disputeId: disputeId + refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk + refundReason: fraudulent + stripeCard: + last4: '4242' + brand: Visa + ownerName: Arthur Dent + expires: + year: 2024 + month: 4 + paypalDetails: + orderId: 1a2b3c4d5e6f7g8h9i0j + payerId: 9k8j7i6h5g4f3e2d1c0b + captureId: qwe123rty456uio789p + refundId: abcde12345fghij67890 + refundReason: Customer requested refund + disputeId: zxcvbnm987poiuytrewq + customData: + - key: value + metadata: + isBuyNow: false + isCustomerDeleted: false + isShippingRequired: true + hasDownloads: false + paymentProcessor: stripe + totals: + subtotal: + unit: USD + value: '5892' + string: ' 109.05 USD' + extras: + - type: tax + name: State Taxes + description: NY Taxes (4.00%) + price: + unit: USD + value: '5892' + string: ' 4.36 USD' + - type: tax + name: City Taxes + description: NEW YORK Taxes (4.88%) + price: + unit: USD + value: '5892' + string: ' 5.32 USD' + - type: shipping + name: Flat + description: '' + price: + unit: USD + value: '5892' + string: ' 0.00 USD' + total: + unit: USD + value: '5892' + string: ' 118.73 USD' + downloadFiles: + - id: 5e9a5eba75e0ac242e1b6f64 + name: New product guide + url: >- + https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa + refund: + path: /sites/{site_id}/orders/{order_id}/refund + method: POST + auth: true + docs: | + This API will reverse a Stripe charge and refund an order back to a + customer. It will also set the order's status to `refunded`. + + Required scope | `ecommerce:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + order_id: + type: string + docs: Unique identifier for an Order + display-name: Refund Order + request: + name: OrdersRefundRequest + body: + properties: + reason: + type: optional + docs: The reason for the refund + content-type: application/json + response: + docs: Request was successful + type: root.Order + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + order_id: 5e8518516e147040726cc415 + request: {} + response: + body: + orderId: fc7-128 + status: refunded + comment: >- + Customer requested gift wrapping and a personalized note saying: + Happy Birthday, Ford! 🎉 Please ensure the item is packed with + extra bubble wrap for safe transit. + orderComment: >- + Please gift wrap with a personal note saying "Happy Birthday, + Ford! 🎉 + acceptedOn: '2024-03-29T21:29:21Z' + fulfilledOn: '2024-03-29T21:29:21Z' + refundedOn: '2024-04-08T18:25:04Z' + disputedOn: '2024-03-29T21:29:21Z' + disputeUpdatedOn: '2024-03-29T21:29:21Z' + disputeLastStatus: charge_refunded + customerPaid: + unit: USD + value: '5892' + string: ' 118.73 USD' + netAmount: + unit: USD + value: '5892' + string: ' 112.62 USD' + applicationFee: + unit: USD + value: '5892' + string: ' 2.37 USD' + allAddresses: + - type: billing + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + - type: shipping + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingAddress: + type: shipping + japanType: kanji + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + billingAddress: + type: billing + japanType: kana + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingProvider: Shipping Company, Co. + shippingTracking: tr00000000001 + shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 + customerInfo: + fullName: Arthur Dent + email: arthur.dent@example.com + purchasedItems: + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 55.61 USD' + productId: 66072fb61b89448912e26791 + productName: Luxurious Fresh Ball + productSlug: luxurious-fresh-ball + variantId: 66072fb71b89448912e2683f + variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' + variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic + variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 55.61 USD' + weight: 11 + width: 82 + height: 70 + length: 9 + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: ' 53.44 USD' + productId: 66072fb61b89448912e26799 + productName: Recycled Steel Gloves + productSlug: recycled-steel-gloves + variantId: 66072fb91b89448912e26ab9 + variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' + variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantImage: + url: >- + https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + variantPrice: + unit: USD + value: '5892' + string: ' 53.44 USD' + weight: 38 + width: 76 + height: 85 + length: 40 + purchasedItemsCount: 2 + stripeDetails: + subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn + paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j + paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft + customerId: cus_PpRsNHwWdUoRKR + chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 + disputeId: disputeId + refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk + refundReason: fraudulent + stripeCard: + last4: '4242' + brand: Visa + ownerName: Arthur Dent + expires: + year: 2024 + month: 4 + paypalDetails: + orderId: 1a2b3c4d5e6f7g8h9i0j + payerId: 9k8j7i6h5g4f3e2d1c0b + captureId: qwe123rty456uio789p + refundId: abcde12345fghij67890 + refundReason: Customer requested refund + disputeId: zxcvbnm987poiuytrewq + customData: + - key: value + metadata: + isBuyNow: false + isCustomerDeleted: false + isShippingRequired: true + hasDownloads: false + paymentProcessor: stripe + totals: + subtotal: + unit: USD + value: '5892' + string: ' 109.05 USD' + extras: + - type: tax + name: State Taxes + description: NY Taxes (4.00%) + price: + unit: USD + value: '5892' + string: ' 4.36 USD' + - type: tax + name: City Taxes + description: NEW YORK Taxes (4.88%) + price: + unit: USD + value: '5892' + string: ' 5.32 USD' + - type: shipping + name: Flat + description: '' + price: + unit: USD + value: '5892' + string: ' 0.00 USD' + total: + unit: USD + value: '5892' + string: ' 118.73 USD' + downloadFiles: + - id: 5e9a5eba75e0ac242e1b6f64 + name: New product guide + url: >- + https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa + source: + openapi: ../../../openapi/referenced-specs/v2.yml + display-name: Orders +docs: Orders are the orders for your Webflow site. diff --git a/.mock/definition/pages.yml b/.mock/definition/pages.yml new file mode 100644 index 0000000..62de7dc --- /dev/null +++ b/.mock/definition/pages.yml @@ -0,0 +1,470 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/pages + method: GET + auth: true + docs: | + List of all pages for a site. + + Required scope | `pages:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Pages + request: + name: PagesListRequest + query-parameters: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + response: + docs: Request was successful + type: root.PageList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + response: + body: + pages: + - id: 6596da6045e56dee495bcbba + siteId: 6258612d1ee792848f805dcf + title: Guide to the Galaxy + slug: guide-to-the-galaxy + parentId: 6419db964a9c435aa3af6251 + collectionId: 6390c49774a71f12831a08e3 + createdOn: '2024-03-11T10:42:00Z' + lastUpdated: '2024-03-11T10:42:42Z' + archived: false + draft: false + canBranch: true + isBranch: false + isMembersOnly: false + seo: + title: The Ultimate Hitchhiker's Guide to the Galaxy + description: >- + Everything you need to know about the galaxy, from + avoiding Vogon poetry to the importance of towels. + openGraph: + title: Explore the Cosmos with The Ultimate Guide + titleCopied: false + description: >- + Dive deep into the mysteries of the universe with your + guide to everything galactic. + descriptionCopied: false + localeId: 653fd9af6a07fc9cfd7a5e57 + publishedPath: /en-us/guide-to-the-galaxy + - id: 6596da6045e56dee495bcbad + siteId: 6258612d1ee792848f805dcf + title: Towel Day Celebrations + slug: towel-day + parentId: 6419db964a9c435aa3af6251 + collectionId: 6390c49774a71f12831a08e3 + createdOn: '2024-05-25T09:00:00Z' + lastUpdated: '2024-05-25T09:42:00Z' + archived: false + draft: false + canBranch: true + isBranch: false + isMembersOnly: false + seo: + title: Celebrate Towel Day - The Hitchhiker's Guide to the Galaxy + description: >- + A guide to celebrating Towel Day, in honor of the most + massively useful thing an interstellar hitchhiker can + have. + openGraph: + title: Towel Day - Don't Panic + titleCopied: false + description: >- + Join the galaxy in celebrating Towel Day, the day + dedicated to carrying towels everywhere in memory of + Douglas Adams. + descriptionCopied: false + localeId: 653fd9af6a07fc9cfd7a5e57 + publishedPath: /en-us/towel-day + pagination: + limit: 20 + offset: 0 + total: 2 + get-metadata: + path: /pages/{page_id} + method: GET + auth: true + docs: | + Get metadata information for a single page. + + Required scope | `pages:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + page_id: + type: string + docs: Unique identifier for a Page + display-name: Get Page Metadata + request: + name: PagesGetMetadataRequest + query-parameters: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + response: + docs: Request was successful + type: root.Page + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + page_id: 63c720f9347c2139b248e552 + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + response: + body: + id: 6596da6045e56dee495bcbba + siteId: 6258612d1ee792848f805dcf + title: Guide to the Galaxy + slug: guide-to-the-galaxy + parentId: 6419db964a9c435aa3af6251 + collectionId: 6390c49774a71f12831a08e3 + createdOn: '2024-03-11T10:42:00Z' + lastUpdated: '2024-03-11T10:42:42Z' + archived: false + draft: false + canBranch: true + isBranch: false + isMembersOnly: false + seo: + title: The Ultimate Hitchhiker's Guide to the Galaxy + description: >- + Everything you need to know about the galaxy, from avoiding + Vogon poetry to the importance of towels. + openGraph: + title: Explore the Cosmos with The Ultimate Guide + titleCopied: false + description: >- + Dive deep into the mysteries of the universe with your guide + to everything galactic. + descriptionCopied: false + localeId: 653fd9af6a07fc9cfd7a5e57 + publishedPath: /en-us/guide-to-the-galaxy + update-page-settings: + path: /pages/{page_id} + method: PUT + auth: true + docs: | + Update Page-level metadata, including SEO and Open Graph fields. + + Required scope | `pages:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + page_id: + type: string + docs: Unique identifier for a Page + display-name: Update Page Metadata + request: + body: root.Page + query-parameters: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + name: UpdatePageSettingsRequest + content-type: application/json + response: + docs: Request was successful + type: root.Page + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + page_id: 63c720f9347c2139b248e552 + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + request: + id: 6596da6045e56dee495bcbba + siteId: 6258612d1ee792848f805dcf + title: Guide to the Galaxy + slug: guide-to-the-galaxy + createdOn: '2024-03-11T10:42:00Z' + lastUpdated: '2024-03-11T10:42:42Z' + archived: false + draft: false + canBranch: true + isBranch: false + seo: + title: The Ultimate Hitchhiker's Guide to the Galaxy + description: >- + Everything you need to know about the galaxy, from avoiding + Vogon poetry to the importance of towels. + openGraph: + title: Explore the Cosmos with The Ultimate Guide + titleCopied: false + description: >- + Dive deep into the mysteries of the universe with your guide to + everything galactic. + descriptionCopied: false + localeId: 653fd9af6a07fc9cfd7a5e57 + publishedPath: /en-us/guide-to-the-galaxy + response: + body: + id: 6596da6045e56dee495bcbba + siteId: 6258612d1ee792848f805dcf + title: Guide to the Galaxy + slug: guide-to-the-galaxy + parentId: 6419db964a9c435aa3af6251 + collectionId: 6390c49774a71f12831a08e3 + createdOn: '2024-03-11T10:42:00Z' + lastUpdated: '2024-03-11T10:42:42Z' + archived: false + draft: false + canBranch: true + isBranch: false + isMembersOnly: false + seo: + title: The Ultimate Hitchhiker's Guide to the Galaxy + description: >- + Everything you need to know about the galaxy, from avoiding + Vogon poetry to the importance of towels. + openGraph: + title: Explore the Cosmos with The Ultimate Guide + titleCopied: false + description: >- + Dive deep into the mysteries of the universe with your guide + to everything galactic. + descriptionCopied: false + localeId: 653fd9af6a07fc9cfd7a5e57 + publishedPath: /en-us/guide-to-the-galaxy + get-content: + path: /pages/{page_id}/dom + method: GET + auth: true + docs: > + Get static content from a static page. This includes text nodes, image + nodes and component instances. + + To retrieve the contents of components in the page use the [get + component + content](/data/reference/pages-and-components/components/get-content) + endpoint. + + + If you do not provide a Locale ID in your request, the response + will return any content that can be localized from the Primary + locale. + + + Required scope | `pages:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + page_id: + type: string + docs: Unique identifier for a Page + display-name: Get Page Content + request: + name: PagesGetContentRequest + query-parameters: + localeId: + type: optional + docs: >- + Unique identifier for a specific locale. Applicable, when using + localization. + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + response: + docs: Request was successful + type: root.Dom + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - name: PageDOM + path-parameters: + page_id: 63c720f9347c2139b248e552 + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + response: + body: + pageId: 658205daa3e8206a523b5ad4 + nodes: + - type: component-instance + id: a245c12d-995b-55ee-5ec7-aa36a6cad623 + componentId: nodes + propertyOverrides: + - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 + - type: component-instance + id: a245c12d-995b-55ee-5ec7-aa36a6cad627 + componentId: nodes + propertyOverrides: + - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 + - type: component-instance + id: a245c12d-995b-55ee-5ec7-aa36a6cad629 + componentId: nodes + propertyOverrides: + - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 + - type: component-instance + id: a245c12d-995b-55ee-5ec7-aa36a6cad631 + componentId: 6258612d1ee792848f805dcf + propertyOverrides: + - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad633 + type: Plain Text + label: Catchphrase + text: + text: Don't Panic! + - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad635 + type: Rich Text + label: Tagline + text: + html:

Always know where your towel is.

+ pagination: + limit: 4 + offset: 0 + total: 4 + update-static-content: + path: /pages/{page_id}/dom + method: POST + auth: true + docs: > + This endpoint updates content on a static page in **secondary locales**. + It supports updating up to 1000 nodes in a single request. + + + Before making updates: + + 1. Use the [get page + content](/data/reference/pages-and-components/pages/get-content) + endpoint to identify available content nodes and their types + + 2. If the page has component instances, retrieve the component's + properties that you'll override using the [get component + properties](/data/reference/pages-and-components/components/get-properties) + endpoint + + + + This endpoint is specifically for localized pages. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + + + Required scope | `pages:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + page_id: + type: string + docs: Unique identifier for a Page + display-name: Update Page Content + request: + name: PageDomWrite + query-parameters: + localeId: + type: string + docs: The locale identifier. + body: + properties: + nodes: + docs: >- + List of DOM Nodes with the new content that will be updated in + each node. + type: list + content-type: application/json + response: + docs: Request was successful + type: UpdateStaticContentResponse + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + page_id: 63c720f9347c2139b248e552 + query-parameters: + localeId: localeId + request: + nodes: + - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad623 + text:

The Hitchhiker's Guide to the Galaxy

+ - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad627 + text: >- +

Don't Panic!

Always know where your towel + is.

+ - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad629 + propertyOverrides: + - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 + text:

Time is an illusion

+ - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f1 + text: Life, the Universe and Everything + response: + body: + errors: + - errors + source: + openapi: ../../../openapi/referenced-specs/v2.yml + display-name: Pages +docs: Pages are the pages in your Webflow site. +types: + PageDomWriteNodesItem: + discriminated: false + union: + - root.TextNodeWrite + - root.ComponentInstanceNodePropertyOverridesWrite + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + UpdateStaticContentResponse: + properties: + errors: + docs: A list of error messages, if any. + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/pages/scripts.yml b/.mock/definition/pages/scripts.yml new file mode 100644 index 0000000..f8ee328 --- /dev/null +++ b/.mock/definition/pages/scripts.yml @@ -0,0 +1,170 @@ +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + get-custom-code: + path: /pages/{page_id}/custom_code + method: GET + auth: true + docs: > + Get all registered scripts that have been applied to a specific Page. + + + In order to use the Custom Code APIs for Sites and Pages, Custom Code + Scripts must first be registered + + to a Site via the `registered_scripts` endpoints, and then applied to a + Site or Page using the appropriate + + `custom_code` endpoints. + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + + + Required scope | `custom_code:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + page_id: + type: string + docs: Unique identifier for a Page + display-name: Get Custom Code + response: + docs: Request was successful + type: root.ScriptApplyList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + page_id: 63c720f9347c2139b248e552 + response: + body: + scripts: + - id: id + location: header + version: version + attributes: + key: value + lastUpdated: lastUpdated + createdOn: createdOn + upsert-custom-code: + path: /pages/{page_id}/custom_code + method: PUT + auth: true + docs: > + Add a registered script to a Page. + + + In order to use the Custom Code APIs for Sites and Pages, Custom Code + Scripts must first be registered + + to a Site via the `registered_scripts` endpoints, and then applied to a + Site or Page using the appropriate + + `custom_code` endpoints. + + + A site can have a maximum of 800 registered scripts. + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + + + Required scope | `custom_code:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + page_id: + type: string + docs: Unique identifier for a Page + display-name: Add/Update Custom Code + request: + body: root.ScriptApplyList + content-type: application/json + response: + docs: Request was successful + type: root.ScriptApplyList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + page_id: 63c720f9347c2139b248e552 + request: + scripts: + - id: cms_slider + location: header + version: 1.0.0 + attributes: + my-attribute: some-value + - id: alert + location: header + version: 0.0.1 + response: + body: + scripts: + - id: cms_slider + location: header + version: 1.0.0 + attributes: + my-attribute: some-value + - id: alert + location: header + version: 0.0.1 + attributes: + key: value + lastUpdated: '2022-10-26T00:28:54.191Z' + createdOn: '2022-10-26T00:28:54.191Z' + delete-custom-code: + path: /pages/{page_id}/custom_code + method: DELETE + auth: true + docs: > + Delete the custom code block that an app has created for a page + + + In order to use the Custom Code APIs for Sites and Pages, Custom Code + Scripts must first be registered + + to a Site via the `registered_scripts` endpoints, and then applied to a + Site or Page using the appropriate + + `custom_code` endpoints. + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + + + Required scope | `custom_code:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + page_id: + type: string + docs: Unique identifier for a Page + display-name: Delete Custom Code + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + page_id: 63c720f9347c2139b248e552 + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/products.yml b/.mock/definition/products.yml new file mode 100644 index 0000000..4c6fcd1 --- /dev/null +++ b/.mock/definition/products.yml @@ -0,0 +1,500 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/products + method: GET + auth: true + docs: > + Retrieve all products for a site. + + + Use `limit` and `offset` to page through all products with subsequent + requests. All SKUs for each product + + will also be fetched and returned. The `limit`, `offset` and `total` + values represent Products only and do not include any SKUs. + + + Required scope | `ecommerce:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Products & SKUs + request: + name: ProductsListRequest + query-parameters: + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + response: + docs: Request was successful + type: root.ProductAndSkUsList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + items: + - product: + id: 660eb7a486d1d6e0412292d7 + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2024-04-04T14:24:19Z' + lastUpdated: '2024-04-04T14:30:19Z' + createdOn: '2024-04-04T14:22:28Z' + isArchived: false + isDraft: false + fieldData: + name: T-Shirt + slug: t-shirt + description: A plain cotton t-shirt. + shippable: true + sku-properties: + - id: Color + name: Color + enum: + - id: id + name: Royal Blue + slug: royal-blue + skus: + - id: 580e63fc8c9a982ac9b8b745 + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35Z' + lastUpdated: '2023-03-17T18:47:35Z' + createdOn: '2023-03-17T18:47:35Z' + fieldData: + sku-values: + ff42fee0113744f693a764e3431a9cc2: 64a74715c456e36762fc39a1 + name: Blue T-shirt + slug: t-shirt-blue + price: + value: 100 + unit: USD + quantity: 10 + pagination: + limit: 100 + offset: 0 + total: 100 + create: + path: /sites/{site_id}/products + method: POST + auth: true + docs: > + Create a new product and SKU. + + + When you create a product, you will always create a SKU, since a Product + Item must have, at minimum, a single SKU. + + + To create a Product with multiple SKUs - for example a T-shirt in sizes + small, medium and large: + - Create parameters in `sku-properties`, also known as [product options and variants.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). + - A single `sku-property` would be `color`. Within the `color` property, list the various colors of T-shirts as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. + - Once, you've created a Product and its `sku-properties` with `enum` values, Webflow will create a **default SKU**, which will automatically be a combination of the first `sku-properties` you've created. + - In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. + - After you've created your product, you can create additional SKUs using the [Create SKU endpoint.](/data/reference/ecommerce/products/create-sku) + + Upon creation, the default product type will be `Advanced`, which + ensures all Product and SKU fields will be shown to users in the + Designer. + + + Required scope | `ecommerce:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Create Product & SKU + request: + name: ProductSkuCreate + body: + properties: + publishStatus: optional + product: optional + sku: optional + content-type: application/json + response: + docs: Request was successful + type: root.ProductAndSkUs + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: {} + response: + body: + product: + id: 660eb7a486d1d6e0412292d7 + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2024-04-04T14:24:19Z' + lastUpdated: '2024-04-04T14:30:19Z' + createdOn: '2024-04-04T14:22:28Z' + isArchived: false + isDraft: false + fieldData: + name: T-Shirt + slug: t-shirt + description: A plain cotton t-shirt. + shippable: true + sku-properties: + - id: Color + name: Color + enum: + - id: id + name: Royal Blue + slug: royal-blue + categories: + - categories + tax-category: standard-taxable + default-sku: default-sku + ec-product-type: ff42fee0113744f693a764e3431a9cc2 + skus: + - id: 580e63fc8c9a982ac9b8b745 + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35Z' + lastUpdated: '2023-03-17T18:47:35Z' + createdOn: '2023-03-17T18:47:35Z' + fieldData: + sku-values: + ff42fee0113744f693a764e3431a9cc2: 64a74715c456e36762fc39a1 + name: Blue T-shirt + slug: t-shirt-blue + price: + value: 100 + unit: USD + quantity: 10 + get: + path: /sites/{site_id}/products/{product_id} + method: GET + auth: true + docs: | + Retrieve a single product by its ID. All of its SKUs will also be + retrieved. + + Required scope | `ecommerce:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + product_id: + type: string + docs: Unique identifier for a Product + display-name: Get Product and SKUs + response: + docs: Request was successful + type: root.ProductAndSkUs + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + product_id: 580e63fc8c9a982ac9b8b745 + response: + body: + product: + id: 660eb7a486d1d6e0412292d7 + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2024-04-04T14:24:19Z' + lastUpdated: '2024-04-04T14:30:19Z' + createdOn: '2024-04-04T14:22:28Z' + isArchived: false + isDraft: false + fieldData: + name: T-Shirt + slug: t-shirt + description: A plain cotton t-shirt. + shippable: true + sku-properties: + - id: Color + name: Color + enum: + - id: id + name: Royal Blue + slug: royal-blue + categories: + - categories + tax-category: standard-taxable + default-sku: default-sku + ec-product-type: ff42fee0113744f693a764e3431a9cc2 + skus: + - id: 580e63fc8c9a982ac9b8b745 + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35Z' + lastUpdated: '2023-03-17T18:47:35Z' + createdOn: '2023-03-17T18:47:35Z' + fieldData: + sku-values: + ff42fee0113744f693a764e3431a9cc2: 64a74715c456e36762fc39a1 + name: Blue T-shirt + slug: t-shirt-blue + price: + value: 100 + unit: USD + quantity: 10 + update: + path: /sites/{site_id}/products/{product_id} + method: PATCH + auth: true + docs: > + Update an existing Product. + + + Updating an existing Product will set the product type to `Advanced`, + which ensures all Product and SKU fields will be shown to users in the + Designer. + + + Required scope | `ecommerce:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + product_id: + type: string + docs: Unique identifier for a Product + display-name: Update Product + request: + name: ProductSkuUpdate + body: + properties: + publishStatus: optional + product: optional + sku: optional + content-type: application/json + response: + docs: Request was successful + type: root.Product + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + product_id: 580e63fc8c9a982ac9b8b745 + request: {} + response: + body: + id: 660eb7a486d1d6e0412292d7 + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2024-04-04T14:24:19Z' + lastUpdated: '2024-04-04T14:30:19Z' + createdOn: '2024-04-04T14:22:28Z' + isArchived: false + isDraft: false + fieldData: + name: T-Shirt + slug: t-shirt + description: A plain cotton t-shirt. + shippable: true + sku-properties: + - id: Color + name: Color + enum: + - id: id + name: Royal Blue + slug: royal-blue + categories: + - categories + tax-category: standard-taxable + default-sku: default-sku + ec-product-type: ff42fee0113744f693a764e3431a9cc2 + create-sku: + path: /sites/{site_id}/products/{product_id}/skus + method: POST + auth: true + docs: > + Create additional SKUs to manage every [option and variant of your + Product.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants) + + + Creating SKUs through the API will set the product type to `Advanced`, + which ensures all Product and SKU fields will be shown to users in the + Designer. + + + Required scope | `ecommerce:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + product_id: + type: string + docs: Unique identifier for a Product + display-name: Create SKU + request: + name: ProductsCreateSkuRequest + body: + properties: + publishStatus: optional + skus: + docs: An array of the SKU data your are adding + type: list + content-type: application/json + response: + docs: Request was successful + type: ProductsCreateSkuResponse + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + product_id: 580e63fc8c9a982ac9b8b745 + request: + skus: + - {} + response: + body: + skus: + - id: 580e63fc8c9a982ac9b8b745 + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35Z' + lastUpdated: '2023-03-17T18:47:35Z' + createdOn: '2023-03-17T18:47:35Z' + fieldData: + sku-values: + ff42fee0113744f693a764e3431a9cc2: 64a74715c456e36762fc39a1 + name: Blue T-shirt + slug: t-shirt-blue + price: + value: 100 + unit: USD + quantity: 10 + update-sku: + path: /sites/{site_id}/products/{product_id}/skus/{sku_id} + method: PATCH + auth: true + docs: > + Update a specified SKU. + + + Updating an existing SKU will set the Product type to `Advanced`, which + ensures all Product and SKU fields will be shown to users in the + Designer. + + + Required scope | `ecommerce:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + product_id: + type: string + docs: Unique identifier for a Product + sku_id: + type: string + docs: Unique identifier for a SKU + display-name: Update SKU + request: + name: ProductsUpdateSkuRequest + body: + properties: + publishStatus: optional + sku: root.Sku + content-type: application/json + response: + docs: Request was successful + type: root.Sku + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + product_id: 580e63fc8c9a982ac9b8b745 + sku_id: 5e8518516e147040726cc415 + request: + sku: {} + response: + body: + id: 580e63fc8c9a982ac9b8b745 + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35Z' + lastUpdated: '2023-03-17T18:47:35Z' + createdOn: '2023-03-17T18:47:35Z' + fieldData: + sku-values: + ff42fee0113744f693a764e3431a9cc2: 64a74715c456e36762fc39a1 + name: Blue T-shirt + slug: t-shirt-blue + price: + value: 100 + unit: USD + compare-at-price: + value: 100 + unit: USD + ec-sku-billing-method: one-time + ec-sku-subscription-plan: + interval: day + frequency: 1 + trial: 7 + plans: + - {} + track-inventory: true + quantity: 10 + source: + openapi: ../../../openapi/referenced-specs/v2.yml +types: + ProductsCreateSkuResponse: + properties: + skus: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/scripts.yml b/.mock/definition/scripts.yml new file mode 100644 index 0000000..8236ed2 --- /dev/null +++ b/.mock/definition/scripts.yml @@ -0,0 +1,253 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/registered_scripts + method: GET + auth: true + docs: > + List of scripts registered to a Site. + + + In order to use the Custom Code APIs for Sites and Pages, Custom Code + Scripts must first be registered + + to a Site via the `registered_scripts` endpoints, and then applied to a + Site or Page using the appropriate + + `custom_code` endpoints. + + Additionally, Scripts can be remotely hosted, or registered as inline + snippets. + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + + + Required scope | `custom_code:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Get Registered Scripts + response: + docs: Request was successful + type: root.RegisteredScriptList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + registeredScripts: + - id: alert + canCopy: false + displayName: Alert + hostedLocation: https://cdn.webflow.io/.../alert-0.0.1.js + integrityHash: integrityHash + createdOn: '2022-10-26T00:28:54.191Z' + lastUpdated: lastUpdated + version: 0.0.1 + - id: alert + canCopy: false + displayName: Alert + hostedLocation: https://cdn.webflow.io/.../alert-0.0.2.js + integrityHash: integrityHash + createdOn: '2022-10-26T00:28:54.191Z' + lastUpdated: lastUpdated + version: 0.0.2 + - id: cms_slider + canCopy: true + displayName: CMS Slider + hostedLocation: https://cdn.jsdelivr.net/.../cms_slider.js + integrityHash: >- + sha384-J+YlJ8v0gpaRoKH7SbFbEmxOZlAxLiwNjfSsBhDooGa5roXlPPpXbEevck4J7YZ+ + createdOn: '2022-10-26T00:28:54.191Z' + lastUpdated: lastUpdated + version: 1.0.0 + register-hosted: + path: /sites/{site_id}/registered_scripts/hosted + method: POST + auth: true + docs: > + Add a script to a Site's Custom Code registry. + + + In order to use the Custom Code APIs for Sites and Pages, Custom Code + Scripts must first be registered + + to a Site via the `registered_scripts` endpoints, and then applied to a + Site or Page using the appropriate + + `custom_code` endpoints. + + Additionally, Scripts can be remotely hosted, or registered as inline + snippets. + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + + + Required scope | `custom_code:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Register Script - Hosted + request: + name: CustomCodeHostedRequest + body: + properties: + hostedLocation: + type: string + docs: URI for an externally hosted script location + integrityHash: + type: string + docs: Sub-Resource Integrity Hash + canCopy: + type: optional + docs: >- + Define whether the script can be copied on site duplication and + transfer + default: false + version: + type: string + docs: >- + A Semantic Version (SemVer) string, denoting the version of the + script + displayName: + type: string + docs: >- + User-facing name for the script. Must be between 1 and 50 + alphanumeric characters + content-type: application/json + response: + docs: Request was successful + type: root.CustomCodeHostedResponse + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + hostedLocation: hostedLocation + integrityHash: integrityHash + version: version + displayName: displayName + response: + body: + id: cms_slider + canCopy: true + displayName: CMS Slider + hostedLocation: https://cdn.jsdelivr.net/.../cmsslider.js + integrityHash: >- + sha384-J+YlJ8v0gpaRoKH7SbFbEmxOZlAxLiwNjfSsBhDooGa5roXlPPpXbEevck4J7YZ+ + createdOn: '2022-10-26T00:28:54.191Z' + lastUpdated: lastUpdated + version: 1.0.0 + register-inline: + path: /sites/{site_id}/registered_scripts/inline + method: POST + auth: true + docs: > + Add a script to a Site's Custom Code registry. Inline scripts can be + between 1 and 2000 characters. + + + In order to use the Custom Code APIs for Sites and Pages, Custom Code + Scripts must first be registered + + to a Site via the `registered_scripts` endpoints, and then applied to a + Site or Page using the appropriate + + `custom_code` endpoints. + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + + + Required scope | `custom_code:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Register Script - Inline + request: + name: CustomCodeInlineRequest + body: + properties: + sourceCode: + type: string + docs: The code to be added to the site (to be hosted by Webflow). + integrityHash: + type: optional + docs: >- + Sub-Resource Integrity Hash. Only required for externally hosted + scripts (passed via hostedLocation) + canCopy: + type: optional + docs: >- + Define whether the script can be copied on site duplication and + transfer + default: false + version: + type: string + docs: >- + A Semantic Version (SemVer) string, denoting the version of the + script + displayName: + type: string + docs: >- + User-facing name for the script. Must be between 1 and 50 + alphanumeric characters + content-type: application/json + response: + docs: Created + type: root.CustomCodeInlineResponse + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + sourceCode: alert('hello world'); + version: 0.0.1 + displayName: Alert + response: + body: + id: alert + canCopy: false + displayName: Alert + hostedLocation: >- + https://uploads-ssl.webflow.com/6258612d1ee792848f805dcf%2F64b6c769ff52ba6c3d904a91%2F660d6e15b3d1696f2d2b1447%2Falert-0.0.1.js + integrityHash: integrityHash + createdOn: '2022-10-26T00:28:54.191Z' + lastUpdated: lastUpdated + version: 0.0.1 + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites.yml b/.mock/definition/sites.yml new file mode 100644 index 0000000..cea8997 --- /dev/null +++ b/.mock/definition/sites.yml @@ -0,0 +1,495 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + create: + path: /workspaces/{workspace_id}/sites + method: POST + auth: true + docs: | + Create a site. This endpoint requires an Enterprise workspace. + + Required scope | `workspace:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + workspace_id: + type: string + docs: Unique identifier for a Workspace + display-name: Create Site + request: + name: SitesCreateRequest + body: + properties: + name: + type: string + docs: The name of the site + templateName: + type: optional + docs: The workspace or marketplace template to use + parentFolderId: + type: optional + docs: MegaDodo Publications - Potential Book Ideas + content-type: application/json + response: + docs: Request was successful + type: root.Site + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - name: NewlyCreatedSite + path-parameters: + workspace_id: 580e63e98c9a982ac9b8b741 + request: + name: The Hitchhiker's Guide to the Galaxy + response: + body: + id: 670ecf86817e3cc7a510eb6a + workspaceId: 625860a7a6c16d624927122f + createdOn: '2024-10-15T20:24:38Z' + displayName: The Hitchiker‘s Guide + shortName: hitchikers-guide + lastPublished: '2016-10-24T19:43:17Z' + lastUpdated: '2024-10-15T20:24:38Z' + previewUrl: >- + https://d1otoma47x30pg.cloudfront.net/580e63e98c9a982ac9b8b741/201610241243.png + timeZone: America/Los_Angeles + parentFolderId: 670ece123598db72d9648be1 + customDomains: + - id: 589a331aa51e760df7ccb89d + url: test-api-domain.com + lastPublished: '2022-12-07T16:51:37Z' + locales: + primary: + id: 653fd9af6a07fc9cfd7a5e57 + cmsLocaleId: 653ad57de882f528b32e810e + enabled: false + displayName: English (United States) + displayImageId: displayImageId + redirect: true + subdirectory: '' + tag: en-US + secondary: + - id: 653fd9af6a07fc9cfd7a5e57 + cmsLocaleId: 653ad57de882f528b32e810e + enabled: false + displayName: English (United States) + redirect: true + subdirectory: '' + tag: en-US + dataCollectionEnabled: false + dataCollectionType: always + list: + path: /sites + method: GET + auth: true + docs: | + List of all sites the provided access token is able to access. + + Required scope | `sites:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + display-name: List Sites + response: + docs: Request was successful + type: root.Sites + errors: + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + examples: + - response: + body: + sites: + - id: 42e63e98c9a982ac9b8b741 + workspaceId: 42e63fc8c9a982ac9b8b744 + createdOn: '1979-10-12T12:00:00Z' + displayName: Heart of Gold Spaceship + shortName: heart-of-gold + lastPublished: '2023-04-02T12:42:00Z' + lastUpdated: '2016-10-24T19:43:17Z' + previewUrl: >- + https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b741/197910121200.png + timeZone: DeepSpace/InfiniteImprobability + parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 + customDomains: + - id: 589a331aa51e760df7ccb89e + url: heartofgold.galaxy + lastPublished: '2022-12-07T16:51:37Z' + locales: + primary: + id: 653fd9af6a07fc9cfd7a5e57 + cmsLocaleId: 653ad57de882f528b32e810e + enabled: true + displayName: English - Heart of Gold Standard + redirect: false + subdirectory: /en + tag: The Ultimate Answer + secondary: + - id: 653fd9af6a07fc9cfd7a5e58 + cmsLocaleId: 653ad57de882f528b32e810g + enabled: true + displayName: Betelgeusian - Vogon Liaison + redirect: true + subdirectory: /bet + tag: Vogon + - id: 653fd9af6a07fc9cfd7a5e59 + cmsLocaleId: 653ad57de882f528b32e810h + enabled: false + displayName: Magrathean - Custom Planet Designs + redirect: true + subdirectory: /mg + tag: Magrathean + dataCollectionEnabled: true + dataCollectionType: always + - id: 42e63e98c9a982ac9b8b742 + workspaceId: 42e63fc8c9a982ac9b8b745 + createdOn: '1981-10-12T12:00:00Z' + displayName: Marvin's Personal Blog + shortName: paranoid-android + lastPublished: '2023-04-02T12:45:00Z' + lastUpdated: '2016-10-24T19:43:17Z' + previewUrl: >- + https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b742/198110121200.png + timeZone: DeepSpace/Depression + parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 + customDomains: + - id: 589a331aa51e760df7ccb89f + url: marvin.blog + lastPublished: '2022-12-07T16:51:37Z' + locales: + primary: + id: 653fd9af6a07fc9cfd7a5e57 + cmsLocaleId: 653ad57de882f528b32e810e + enabled: true + displayName: English - Marvin's Musings + redirect: false + subdirectory: /en + tag: English + secondary: + - id: 653fd9af6a07fc9cfd7a5e56 + cmsLocaleId: 653ad57de882f528b32e810f + enabled: true + displayName: Squornshellous - Mattress Speak + redirect: true + subdirectory: /sr + tag: Squornshellous + dataCollectionEnabled: true + dataCollectionType: always + - id: 42e63e98c9a982ac9b8b743 + workspaceId: 42e63fc8c9a982ac9b8b746 + createdOn: '1982-10-12T12:00:00Z' + displayName: Vogon Poetry Archive + shortName: vogon-poetry + lastPublished: '2023-04-02T12:50:00Z' + lastUpdated: '2016-10-24T19:43:17Z' + previewUrl: >- + https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b743/198210121200.png + timeZone: Vogsphere/PoetryHall + parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 + customDomains: + - id: 589a331aa51e760df7ccb8a0 + url: vogonpoetry.galaxy + lastPublished: '2022-12-07T16:51:37Z' + locales: + primary: + id: 653fd9af6a07fc9cfd7a5e55 + cmsLocaleId: 653ad57de882f528b32e810d + enabled: true + displayName: English - Vogon Verse + redirect: false + subdirectory: /en + tag: Third Worst Poetry + secondary: + - id: 653fd9af6a07fc9cfd7a5e54 + cmsLocaleId: 653ad57de882f528b32e810c + enabled: true + displayName: Galactic - Universal Language + redirect: true + subdirectory: /gl + tag: Pan-Galactic Gargle Blaster + dataCollectionEnabled: true + dataCollectionType: always + get: + path: /sites/{site_id} + method: GET + auth: true + docs: | + Get details of a site. + + Required scope | `sites:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Get Site + response: + docs: Request was successful + type: root.Site + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + id: 42e98c9a982ac9b8b742 + workspaceId: 42e63e98c9a982ac9b8b742 + createdOn: '1979-10-12T12:00:00Z' + displayName: The Hitchhiker's Guide to the Galaxy + shortName: hitchhikers-guide + lastPublished: '2023-04-02T12:42:00Z' + lastUpdated: '2023-04-02T12:42:00Z' + previewUrl: >- + https://screenshots.webflow.com/sites/6258612d1ee792848f805dcf/20231219211811_d5990556c743f33b7071300a03bf67e6.png + timeZone: Magrathea/FactoryFloor + parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 + customDomains: + - id: 589a331aa51e760df7ccb89d + url: hitchhikersguide.galaxy + lastPublished: '2022-12-07T16:51:37Z' + - id: 589a331aa51e760df7ccb89e + url: heartofgold.spaceship + lastPublished: '2022-12-07T16:51:37Z' + locales: + primary: + id: 653fd9af6a07fc9cfd7a5e57 + cmsLocaleId: 653ad57de882f528b32e810e + enabled: false + displayName: English (United States) + displayImageId: displayImageId + redirect: true + subdirectory: '' + tag: en-US + secondary: + - id: 653fd9af6a07fc9cfd7a5e57 + cmsLocaleId: 653ad57de882f528b32e810e + enabled: false + displayName: English (United States) + redirect: true + subdirectory: '' + tag: en-US + dataCollectionEnabled: true + dataCollectionType: always + delete: + path: /sites/{site_id} + method: DELETE + auth: true + docs: | + Delete a site. This endpoint requires an Enterprise workspace. + + Required scope | `sites:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Delete Site + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + update: + path: /sites/{site_id} + method: PATCH + auth: true + docs: | + Update a site. This endpoint requires an Enterprise workspace. + + Required scope | `sites:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Update Site + request: + name: SitesUpdateRequest + body: + properties: + name: + type: optional + docs: The name of the site + parentFolderId: + type: optional + docs: The parent folder ID of the site + content-type: application/json + response: + docs: Request was successful + type: root.Site + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: {} + response: + body: + id: 42e98c9a982ac9b8b742 + workspaceId: 42e63e98c9a982ac9b8b742 + createdOn: '1979-10-12T12:00:00Z' + displayName: The Hitchhiker's Guide to the Galaxy + shortName: hitchhikers-guide + lastPublished: '2023-04-02T12:42:00Z' + lastUpdated: '2023-04-02T12:42:00Z' + previewUrl: >- + https://screenshots.webflow.com/sites/6258612d1ee792848f805dcf/20231219211811_d5990556c743f33b7071300a03bf67e6.png + timeZone: Magrathea/FactoryFloor + parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 + customDomains: + - id: 589a331aa51e760df7ccb89d + url: hitchhikersguide.galaxy + lastPublished: '2022-12-07T16:51:37Z' + - id: 589a331aa51e760df7ccb89e + url: heartofgold.spaceship + lastPublished: '2022-12-07T16:51:37Z' + locales: + primary: + id: 653fd9af6a07fc9cfd7a5e57 + cmsLocaleId: 653ad57de882f528b32e810e + enabled: false + displayName: English (United States) + displayImageId: displayImageId + redirect: true + subdirectory: '' + tag: en-US + secondary: + - id: 653fd9af6a07fc9cfd7a5e57 + cmsLocaleId: 653ad57de882f528b32e810e + enabled: false + displayName: English (United States) + redirect: true + subdirectory: '' + tag: en-US + dataCollectionEnabled: true + dataCollectionType: always + get-custom-domain: + path: /sites/{site_id}/custom_domains + method: GET + auth: true + docs: | + Get a list of all custom domains related to site. + + Required scope | `sites:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Get Custom Domains + response: + docs: Request was successful + type: root.Domains + errors: + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + customDomains: + - id: 589a331aa51e760df7ccb89d + url: hitchhikersguide.galaxy + lastPublished: '2022-12-07T16:51:37Z' + - id: 589a331aa51e760df7ccb89e + url: heartofgold.spaceship + lastPublished: '2022-12-07T16:51:37Z' + publish: + path: /sites/{site_id}/publish + method: POST + auth: true + docs: > + Publishes a site to one or more more domains. + + + This endpoint has a limit of + one successful publish queue per minute. + + + Required scope | `sites:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Publish Site + request: + name: SitesPublishRequest + body: + properties: + customDomains: + type: optional> + docs: Array of Custom Domain IDs to publish + publishToWebflowSubdomain: + type: optional + docs: Choice of whether to publish to the default Webflow Subdomain + default: false + content-type: application/json + response: + docs: Request accepted + type: SitesPublishResponse + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: {} + response: + body: + customDomains: + - id: 589a331aa51e760df7ccb89d + url: test-api-domain.com + lastPublished: '2022-12-07T16:51:37Z' + publishToWebflowSubdomain: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + display-name: Sites +docs: Sites are the sites in your Webflow workspace. +types: + SitesPublishResponse: + properties: + customDomains: + type: optional> + docs: Array of domains objects + publishToWebflowSubdomain: + type: optional + docs: Flag for publishing to webflow.io subdomain + default: false + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/activityLogs.yml b/.mock/definition/sites/activityLogs.yml new file mode 100644 index 0000000..1468f52 --- /dev/null +++ b/.mock/definition/sites/activityLogs.yml @@ -0,0 +1,65 @@ +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/activity_logs + method: GET + auth: true + docs: >- + Retrieve Activity Logs for a specific Site. Requires Site to be on an + Enterprise plan.

Required scope | `site_activity:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Get Site Activity Logs + request: + name: ActivityLogsListRequest + query-parameters: + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + response: + docs: A list of site activity logs + type: root.SiteActivityLogResponse + errors: + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + items: + - id: 654c16c7b229e56bcf26872d + createdOn: '2023-11-08T23:16:23Z' + lastUpdated: '2023-11-08T23:16:23Z' + event: cms_collection + resourceOperation: CREATED + user: + id: 6509cd56e90eec668b009712 + displayName: John Doe + resourceId: 654c16c7b229e56bcf26870c + resourceName: foo-bar + newValue: newValue + previousValue: previousValue + payload: + key: value + pagination: + limit: 25 + offset: 0 + total: 1 + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/plans.yml b/.mock/definition/sites/plans.yml new file mode 100644 index 0000000..ae9de6d --- /dev/null +++ b/.mock/definition/sites/plans.yml @@ -0,0 +1,40 @@ +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + get-site-plan: + path: /sites/{site_id}/plan + method: GET + auth: true + docs: | + Get site plan details for the specified Site. + + Required scope | `sites:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Get Site Plan + response: + docs: Request was successful + type: root.SitePlan + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + id: hosting-business-v4 + name: Business Hosting + pricingInfo: https://webflow.com/pricing + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/redirects.yml b/.mock/definition/sites/redirects.yml new file mode 100644 index 0000000..b104d86 --- /dev/null +++ b/.mock/definition/sites/redirects.yml @@ -0,0 +1,190 @@ +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/redirects + method: GET + auth: true + docs: > + Fetch a list of all URL redirect rules configured for a specific site. + + + Use this endpoint to review, audit, or manage the redirection rules that + control how traffic is rerouted on your site. + + + + Required scope: `sites:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Get URL redirects + response: + docs: Request was successful + type: root.Redirects + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + redirects: + - id: 42e1a2b7aa1a13f768a0042a + fromUrl: /mostly-harmless + toUrl: /earth + - id: 6x9e7f8d9a4b1c2d3e4f5678 + fromUrl: /babel-fish + toUrl: /translate + pagination: + limit: 100 + offset: 0 + total: 2 + create: + path: /sites/{site_id}/redirects + method: POST + auth: true + docs: > + Add a new URL redirection rule to a site. + + + This endpoint allows you to define a source path (`fromUrl`) and its + corresponding destination path (`toUrl`), which will dictate how traffic + is rerouted on your site. This is useful for managing site changes, + restructuring URLs, or handling outdated links. + + + Required scope: `sites:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Create a URL redirect + request: + body: root.Redirect + content-type: application/json + response: + docs: Request was successful + type: root.Redirect + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + id: 42e1a2b7aa1a13f768a0042a + fromUrl: /mostly-harmless + toUrl: /earth + response: + body: + id: 42e1a2b7aa1a13f768a0042a + fromUrl: /mostly-harmless + toUrl: /earth + delete: + path: /sites/{site_id}/redirects/{redirect_id} + method: DELETE + auth: true + docs: > + Remove a URL redirection rule from a site. + + This is useful for cleaning up outdated or unnecessary redirects, + ensuring that your site's routing behavior remains efficient and + up-to-date. + + Required scope: `sites:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + redirect_id: + type: string + docs: Unique identifier site rediect + display-name: Delete URL redirects + response: + docs: Request was successful + type: root.Redirects + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + redirect_id: 66c4cb9a20cac35ed19500e6 + response: + body: + redirects: + - id: 42e1a2b7aa1a13f768a0042a + fromUrl: /mostly-harmless + toUrl: /earth + - id: 6x9e7f8d9a4b1c2d3e4f5678 + fromUrl: /babel-fish + toUrl: /translate + pagination: + limit: 100 + offset: 0 + total: 2 + update: + path: /sites/{site_id}/redirects/{redirect_id} + method: PATCH + auth: true + docs: | + Update a URL redirection rule from a site. + Required scope: `sites:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + redirect_id: + type: string + docs: Unique identifier site rediect + display-name: Update URL redirect + request: + body: root.Redirect + content-type: application/json + response: + docs: Request was successful + type: root.Redirect + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + redirect_id: 66c4cb9a20cac35ed19500e6 + request: + id: 42e1a2b7aa1a13f768a0042a + fromUrl: /mostly-harmless + toUrl: /earth + response: + body: + id: 42e1a2b7aa1a13f768a0042a + fromUrl: /mostly-harmless + toUrl: /earth + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/scripts.yml b/.mock/definition/sites/scripts.yml new file mode 100644 index 0000000..92ad0e4 --- /dev/null +++ b/.mock/definition/sites/scripts.yml @@ -0,0 +1,223 @@ +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + get-custom-code: + path: /sites/{site_id}/custom_code + method: GET + auth: true + docs: > + Get all registered scripts that have been applied to a specific Site. + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + + + Required scope | `custom_code:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Get Custom Code + response: + docs: Request was successful + type: root.ScriptApplyList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + scripts: + - id: cms_slider + location: header + version: 1.0.0 + attributes: + my-attribute: some-value + - id: alert + location: header + version: 0.0.1 + attributes: + key: value + lastUpdated: '2022-10-26T00:28:54.191Z' + createdOn: '2022-10-26T00:28:54.191Z' + upsert-custom-code: + path: /sites/{site_id}/custom_code + method: PUT + auth: true + docs: > + Add a registered script to a Site. + + + In order to use the Custom Code APIs for Sites and Pages, Custom Code + Scripts must first be registered + + to a Site via the `registered_scripts` endpoints, and then applied to a + Site or Page using the appropriate + + `custom_code` endpoints. + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + + + Required scope | `custom_code:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Add/Update Custom Code + request: + body: root.ScriptApplyList + content-type: application/json + response: + docs: Request was successful + type: root.ScriptApplyList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + scripts: + - id: cms_slider + location: header + version: 1.0.0 + attributes: + my-attribute: some-value + - id: alert + location: header + version: 0.0.1 + response: + body: + scripts: + - id: cms_slider + location: header + version: 1.0.0 + attributes: + my-attribute: some-value + - id: alert + location: header + version: 0.0.1 + attributes: + key: value + lastUpdated: lastUpdated + createdOn: createdOn + delete-custom-code: + path: /sites/{site_id}/custom_code + method: DELETE + auth: true + docs: > + Delete the custom code block that an app created for a Site + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + + + Required scope | `custom_code:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Delete Custom Code + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + list-custom-code-blocks: + path: /sites/{site_id}/custom_code/blocks + method: GET + auth: true + docs: > + Get all instances of Custom Code applied to a Site or Pages. + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + + + Required scope | `custom_code:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Custom Code Blocks + request: + name: ScriptsListCustomCodeBlocksRequest + query-parameters: + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + response: + docs: Request was successful + type: root.ListCustomCodeBlocks + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + blocks: + - siteId: 6258612d1ee792848f805dcf + pageId: pageId + type: site + scripts: + - id: chartjs + location: header + version: 4.4.2 + attributes: + key: value + createdOn: '2024-04-03T16:49:15Z' + lastUpdated: '2024-04-03T16:49:15Z' + - siteId: 6390c49674a71f84b51a08d8 + pageId: 6419db964a9c43f6a3af6348 + type: page + scripts: + - id: id + location: header + version: version + createdOn: '2022-10-26T00:28:54Z' + lastUpdated: '2022-10-26T00:28:54Z' + pagination: + limit: 10 + offset: 0 + total: 1 + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/token.yml b/.mock/definition/token.yml new file mode 100644 index 0000000..033c5c3 --- /dev/null +++ b/.mock/definition/token.yml @@ -0,0 +1,72 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + authorized-by: + path: /token/authorized_by + method: GET + auth: true + docs: | + Information about the Authorized User + + Required Scope | `authorized_user:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + display-name: Get Authorization User Info + response: + docs: Request was successful + type: root.AuthorizedUser + errors: + - root.UnauthorizedError + - root.ForbiddenError + examples: + - response: + body: + id: 545bbecb7bdd6769632504a7 + email: some@email.com + firstName: Some + lastName: One + introspect: + path: /token/introspect + method: GET + auth: true + docs: > + Information about the authorization token + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + source: + openapi: ../../../openapi/referenced-specs/v2.yml + display-name: Get Authorization Info + response: + docs: Request was successful + type: root.Authorization + errors: + - root.UnauthorizedError + examples: + - response: + body: + authorization: + id: 55818d58616600637b9a5786 + createdOn: '2016-10-03T23:12:00Z' + lastUsed: '2016-10-10T21:41:12Z' + grantType: authorization_code + rateLimit: 60 + scope: assets:read,assets:write + authorizedTo: + siteIds: + - 62f3b1f7eafac55d0c64ef91 + workspaceIds: + - 52f3b1f7eafac55d0c64ef91 + userIds: + - 545bbecb7bdd6769632504a7 + application: + id: 55131cd036c09f7d07883dfc + description: My Amazing App + homepage: https://webflow.com + displayName: My Amazing App + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/users.yml b/.mock/definition/users.yml new file mode 100644 index 0000000..19a17cc --- /dev/null +++ b/.mock/definition/users.yml @@ -0,0 +1,392 @@ +types: + UsersListRequestSort: + enum: + - value: CreatedOn + name: CreatedOnAscending + docs: Sorts users in ascending order based on their created date + - value: '-CreatedOn' + name: CreatedOnDescending + docs: Sorts users in descending order based on their created date + - value: Email + name: EmailAscending + docs: Sorts users in ascending order based on their email + - value: '-Email' + name: EmailDescending + docs: Sorts users in descending order based on their email + - value: Status + name: StatusAscending + docs: Sorts users in ascending order based on their status + - value: '-Status' + name: StatusDescending + docs: Sorts users in descending order based on their status + - value: LastLogin + name: LastLoginAscending + docs: Sorts users in ascending order based on their last login date + - value: '-LastLogin' + name: LastLoginDescending + docs: Sorts users in descending order based on their last login date + - value: UpdatedOn + name: UpdatedOnAscending + docs: Sorts users in ascending order based on their update date + - value: '-UpdatedOn' + name: UpdatedOnDescending + docs: Sorts users in descending order based on their update date + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UsersUpdateRequestData: + properties: + name: + type: optional + docs: | + The name of the user + accept-privacy: + type: optional + docs: | + Boolean indicating if the user has accepted the privacy policy + accept-communications: + type: optional + docs: | + Boolean indicating if the user has accepted to receive communications + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/users + method: GET + auth: true + docs: | + Get a list of users for a site + + Required scope | `users:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Users + request: + name: UsersListRequest + query-parameters: + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + sort: + type: optional + docs: | + Sort string to use when ordering users + + Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). + + Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) + response: + docs: Request was successful + type: root.UserList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + count: 5 + limit: 5 + offset: 0 + total: 201 + users: + - id: 6287ec36a841b25637c663df + isEmailVerified: false + lastUpdated: '2022-05-20T13:46:12Z' + invitedOn: '2016-10-24T19:41:29Z' + createdOn: '2022-05-20T13:46:12Z' + lastLogin: '2016-10-24T19:41:29Z' + status: unverified + accessGroups: + - slug: vogon-construction-crew + type: admin + - id: 6287ec36a841b25637c663f0 + isEmailVerified: false + lastUpdated: '2022-05-19T05:32:04Z' + invitedOn: '2016-10-24T19:41:29Z' + createdOn: '2022-05-19T05:32:04Z' + lastLogin: '2016-10-24T19:41:29Z' + status: unverified + accessGroups: + - slug: improbability-drive-test-subjects + type: admin + - id: 6287ec36a841b25637c663d9 + isEmailVerified: true + lastUpdated: '2022-05-17T03:34:06Z' + invitedOn: '2016-10-24T19:41:29Z' + createdOn: '2022-05-17T03:34:06Z' + lastLogin: '2016-10-24T19:41:29Z' + status: verified + accessGroups: + - slug: heart-of-gold-crew + type: admin + - id: 6287ec37a841b25637c6641b + isEmailVerified: false + lastUpdated: '2022-05-15T03:46:09Z' + invitedOn: '2016-10-24T19:41:29Z' + createdOn: '2022-05-15T03:46:09Z' + lastLogin: '2016-10-24T19:41:29Z' + status: unverified + accessGroups: + - slug: hitchhikers-guide-research-team + type: admin + - id: 6287ec37a841b25637c66449 + isEmailVerified: true + lastUpdated: '2022-05-15T02:55:38Z' + invitedOn: '2016-10-24T19:41:29Z' + createdOn: '2022-05-15T02:55:38Z' + lastLogin: '2016-10-24T19:41:29Z' + status: verified + accessGroups: + - slug: milliways-reservationists + type: admin + get: + path: /sites/{site_id}/users/{user_id} + method: GET + auth: true + docs: | + Get a User by ID + + Required scope | `users:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + user_id: + type: string + docs: Unique identifier for a User + display-name: Get User + response: + docs: Request was successful + type: root.User + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + user_id: 580e63e98c9a982ac9b8b741 + response: + body: + id: 6287ec36a841b25637c663df + isEmailVerified: true + lastUpdated: '2022-05-20T13:46:12Z' + invitedOn: '2022-05-20T13:46:12Z' + createdOn: '2022-05-20T13:46:12Z' + lastLogin: '2022-05-20T13:46:12Z' + status: verified + accessGroups: + - slug: webflowers + type: admin + data: + data: + name: name + email: email + accept-privacy: true + accept-communications: true + additionalProperties: additionalProperties + delete: + path: /sites/{site_id}/users/{user_id} + method: DELETE + auth: true + docs: | + Delete a User by ID + + Required scope | `users:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + user_id: + type: string + docs: Unique identifier for a User + display-name: Delete User + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + user_id: 580e63e98c9a982ac9b8b741 + update: + path: /sites/{site_id}/users/{user_id} + method: PATCH + auth: true + docs: | + Update a User by ID + + Required scope | `users:write` + + The email and password + fields cannot be updated using this endpoint + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + user_id: + type: string + docs: Unique identifier for a User + display-name: Update User + request: + name: UsersUpdateRequest + body: + properties: + data: optional + accessGroups: + type: optional> + docs: > + An array of access group slugs. Access groups are assigned to + the user as type `admin` and the user remains in the group until + removed. + content-type: application/json + response: + docs: Request was successful + type: root.User + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + user_id: 580e63e98c9a982ac9b8b741 + request: + data: + name: Some One + accept-privacy: false + accept-communications: false + accessGroups: + - webflowers + - platinum + - free-tier + response: + body: + id: 6287ec36a841b25637c663df + isEmailVerified: true + lastUpdated: '2022-05-20T13:46:12Z' + invitedOn: '2022-05-20T13:46:12Z' + createdOn: '2022-05-20T13:46:12Z' + lastLogin: '2022-05-20T13:46:12Z' + status: verified + accessGroups: + - slug: webflowers + type: admin + data: + data: + name: name + email: email + accept-privacy: true + accept-communications: true + additionalProperties: additionalProperties + invite: + path: /sites/{site_id}/users/invite + method: POST + auth: true + docs: > + Create and invite a user with an email address. + + + The user will be sent and invite via email, which they will need to + accept in order to join paid any paid access group. + + + Required scope | `users:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Create and Invite a User + request: + name: UsersInviteRequest + body: + properties: + email: + type: string + docs: Email address of user to send invite to + validation: + format: email + accessGroups: + type: optional> + docs: > + An array of access group slugs. Access groups are assigned to + the user as type `admin` and the user remains in the group until + removed. + content-type: application/json + response: + docs: Request was successful + type: root.User + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + email: some.one@home.com + accessGroups: + - webflowers + response: + body: + id: 6287ec36a841b25637c663df + isEmailVerified: true + lastUpdated: '2022-05-20T13:46:12Z' + invitedOn: '2022-05-20T13:46:12Z' + createdOn: '2022-05-20T13:46:12Z' + lastLogin: '2022-05-20T13:46:12Z' + status: verified + accessGroups: + - slug: webflowers + type: admin + data: + data: + name: name + email: email + accept-privacy: true + accept-communications: true + additionalProperties: additionalProperties + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/webhooks.yml b/.mock/definition/webhooks.yml new file mode 100644 index 0000000..d40e3e4 --- /dev/null +++ b/.mock/definition/webhooks.yml @@ -0,0 +1,189 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + list: + path: /sites/{site_id}/webhooks + method: GET + auth: true + docs: | + List all App-created Webhooks registered for a given site + + Required scope | `sites:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Webhooks + response: + docs: Request was successful + type: root.WebhookList + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + pagination: + limit: 100 + offset: 0 + total: 100 + webhooks: + - id: 57ca0a9e418c504a6e1acbb6 + triggerType: form_submission + url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f + workspaceId: 4f4e46fd476ea8c507000001 + siteId: 562ac0395358780a1f5e6fbd + filter: + name: Email Form + lastTriggered: '2023-02-08T23:59:28Z' + createdOn: '2016-09-02T23:26:22Z' + - id: 578d85cce0c47cd2865f4cf2 + triggerType: form_submission + url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f + workspaceId: 4f4e46fd476ea8c507000001 + siteId: 562ac0395358780a1f5e6fbd + filter: + name: Email Form + lastTriggered: '2023-02-08T23:59:28Z' + createdOn: '2016-07-19T01:43:40Z' + - id: 578d85cce0c47cd2865f4cf3 + triggerType: form_submission + url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f + workspaceId: 4f4e46fd476ea8c507000001 + siteId: 562ac0395358780a1f5e6fbd + filter: + name: Email Form + lastTriggered: '2023-02-08T23:59:28Z' + createdOn: '2016-07-19T01:43:40Z' + create: + path: /sites/{site_id}/webhooks + method: POST + auth: true + docs: > + Create a new Webhook. + + + Limit of 75 registrations per `triggerType`, per site. + + + Access to this endpoint requires a bearer token from a [Data + Client App](/data/docs/getting-started-data-clients). + + Required scope | `sites:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Create Webhook + request: + body: root.Webhook + content-type: application/json + response: + docs: Request was successful + type: root.Webhook + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + id: 582266e0cd48de0f0e3c6d8b + triggerType: form_submission + url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f + workspaceId: 4f4e46fd476ea8c507000001 + siteId: 562ac0395358780a1f5e6fbd + lastTriggered: '2023-02-08T23:59:28Z' + createdOn: '2022-11-08T23:59:28Z' + response: + body: + id: 582266e0cd48de0f0e3c6d8b + triggerType: form_submission + url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f + workspaceId: 4f4e46fd476ea8c507000001 + siteId: 562ac0395358780a1f5e6fbd + filter: + name: My Form + lastTriggered: '2023-02-08T23:59:28Z' + createdOn: '2022-11-08T23:59:28Z' + get: + path: /webhooks/{webhook_id} + method: GET + auth: true + docs: | + Get a specific Webhook instance + + Required scope: `sites:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + webhook_id: + type: string + docs: Unique identifier for a Webhook + display-name: Get Webhook + response: + docs: Request was successful + type: root.Webhook + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + webhook_id: 580e64008c9a982ac9b8b754 + response: + body: + id: 582266e0cd48de0f0e3c6d8b + triggerType: form_submission + url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f + workspaceId: 4f4e46fd476ea8c507000001 + siteId: 562ac0395358780a1f5e6fbd + filter: + name: My Form + lastTriggered: '2023-02-08T23:59:28Z' + createdOn: '2022-11-08T23:59:28Z' + delete: + path: /webhooks/{webhook_id} + method: DELETE + auth: true + docs: | + Remove a Webhook + + Required scope: `sites:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + webhook_id: + type: string + docs: Unique identifier for a Webhook + display-name: Remove Webhook + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + webhook_id: 580e64008c9a982ac9b8b754 + source: + openapi: ../../../openapi/referenced-specs/v2.yml + display-name: Webhooks +docs: Webhooks are the webhooks in your Webflow site. diff --git a/.mock/fern.config.json b/.mock/fern.config.json new file mode 100644 index 0000000..8b3316e --- /dev/null +++ b/.mock/fern.config.json @@ -0,0 +1,4 @@ +{ + "organization" : "webflow", + "version" : "0.46.19" +} \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index a257797..a563308 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "annotated-types" @@ -16,13 +16,13 @@ typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} [[package]] name = "anyio" -version = "4.4.0" +version = "4.5.2" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.8" files = [ - {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, - {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, + {file = "anyio-4.5.2-py3-none-any.whl", hash = "sha256:c011ee36bc1e8ba40e5a81cb9df91925c218fe9b778554e0b56a21e1b5d4716f"}, + {file = "anyio-4.5.2.tar.gz", hash = "sha256:23009af4ed04ce05991845451e11ef02fc7c5ed29179ac9a420e5ad0ac7ddc5b"}, ] [package.dependencies] @@ -32,19 +32,19 @@ sniffio = ">=1.1" typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (>=0.23)"] +doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21.0b1)"] +trio = ["trio (>=0.26.1)"] [[package]] name = "certifi" -version = "2024.6.2" +version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"}, - {file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"}, + {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, + {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, ] [[package]] @@ -60,13 +60,13 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] @@ -85,13 +85,13 @@ files = [ [[package]] name = "httpcore" -version = "1.0.5" +version = "1.0.7" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, - {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, + {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, + {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, ] [package.dependencies] @@ -102,17 +102,17 @@ h11 = ">=0.13,<0.15" asyncio = ["anyio (>=4.0,<5.0)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.26.0)"] +trio = ["trio (>=0.22.0,<1.0)"] [[package]] name = "httpx" -version = "0.27.0" +version = "0.28.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, - {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, ] [package.dependencies] @@ -120,25 +120,28 @@ anyio = "*" certifi = "*" httpcore = "==1.*" idna = "*" -sniffio = "*" [package.extras] brotli = ["brotli", "brotlicffi"] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "idna" -version = "3.7" +version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, ] +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -209,13 +212,13 @@ files = [ [[package]] name = "packaging" -version = "24.1" +version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, - {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, + {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, + {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, ] [[package]] @@ -235,109 +238,131 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pydantic" -version = "2.7.4" +version = "2.10.5" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.7.4-py3-none-any.whl", hash = "sha256:ee8538d41ccb9c0a9ad3e0e5f07bf15ed8015b481ced539a1759d8cc89ae90d0"}, - {file = "pydantic-2.7.4.tar.gz", hash = "sha256:0c84efd9548d545f63ac0060c1e4d39bb9b14db8b3c0652338aecc07b5adec52"}, + {file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"}, + {file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"}, ] [package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.18.4" -typing-extensions = ">=4.6.1" +annotated-types = ">=0.6.0" +pydantic-core = "2.27.2" +typing-extensions = ">=4.12.2" [package.extras] email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata"] [[package]] name = "pydantic-core" -version = "2.18.4" +version = "2.27.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.18.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f76d0ad001edd426b92233d45c746fd08f467d56100fd8f30e9ace4b005266e4"}, - {file = "pydantic_core-2.18.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:59ff3e89f4eaf14050c8022011862df275b552caef8082e37b542b066ce1ff26"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a55b5b16c839df1070bc113c1f7f94a0af4433fcfa1b41799ce7606e5c79ce0a"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4d0dcc59664fcb8974b356fe0a18a672d6d7cf9f54746c05f43275fc48636851"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8951eee36c57cd128f779e641e21eb40bc5073eb28b2d23f33eb0ef14ffb3f5d"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4701b19f7e3a06ea655513f7938de6f108123bf7c86bbebb1196eb9bd35cf724"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e00a3f196329e08e43d99b79b286d60ce46bed10f2280d25a1718399457e06be"}, - {file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97736815b9cc893b2b7f663628e63f436018b75f44854c8027040e05230eeddb"}, - {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6891a2ae0e8692679c07728819b6e2b822fb30ca7445f67bbf6509b25a96332c"}, - {file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bc4ff9805858bd54d1a20efff925ccd89c9d2e7cf4986144b30802bf78091c3e"}, - {file = "pydantic_core-2.18.4-cp310-none-win32.whl", hash = "sha256:1b4de2e51bbcb61fdebd0ab86ef28062704f62c82bbf4addc4e37fa4b00b7cbc"}, - {file = "pydantic_core-2.18.4-cp310-none-win_amd64.whl", hash = "sha256:6a750aec7bf431517a9fd78cb93c97b9b0c496090fee84a47a0d23668976b4b0"}, - {file = "pydantic_core-2.18.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:942ba11e7dfb66dc70f9ae66b33452f51ac7bb90676da39a7345e99ffb55402d"}, - {file = "pydantic_core-2.18.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b2ebef0e0b4454320274f5e83a41844c63438fdc874ea40a8b5b4ecb7693f1c4"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a642295cd0c8df1b86fc3dced1d067874c353a188dc8e0f744626d49e9aa51c4"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f09baa656c904807e832cf9cce799c6460c450c4ad80803517032da0cd062e2"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98906207f29bc2c459ff64fa007afd10a8c8ac080f7e4d5beff4c97086a3dabd"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19894b95aacfa98e7cb093cd7881a0c76f55731efad31073db4521e2b6ff5b7d"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fbbdc827fe5e42e4d196c746b890b3d72876bdbf160b0eafe9f0334525119c8"}, - {file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f85d05aa0918283cf29a30b547b4df2fbb56b45b135f9e35b6807cb28bc47951"}, - {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e85637bc8fe81ddb73fda9e56bab24560bdddfa98aa64f87aaa4e4b6730c23d2"}, - {file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2f5966897e5461f818e136b8451d0551a2e77259eb0f73a837027b47dc95dab9"}, - {file = "pydantic_core-2.18.4-cp311-none-win32.whl", hash = "sha256:44c7486a4228413c317952e9d89598bcdfb06399735e49e0f8df643e1ccd0558"}, - {file = "pydantic_core-2.18.4-cp311-none-win_amd64.whl", hash = "sha256:8a7164fe2005d03c64fd3b85649891cd4953a8de53107940bf272500ba8a788b"}, - {file = "pydantic_core-2.18.4-cp311-none-win_arm64.whl", hash = "sha256:4e99bc050fe65c450344421017f98298a97cefc18c53bb2f7b3531eb39bc7805"}, - {file = "pydantic_core-2.18.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6f5c4d41b2771c730ea1c34e458e781b18cc668d194958e0112455fff4e402b2"}, - {file = "pydantic_core-2.18.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2fdf2156aa3d017fddf8aea5adfba9f777db1d6022d392b682d2a8329e087cef"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4748321b5078216070b151d5271ef3e7cc905ab170bbfd27d5c83ee3ec436695"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847a35c4d58721c5dc3dba599878ebbdfd96784f3fb8bb2c356e123bdcd73f34"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c40d4eaad41f78e3bbda31b89edc46a3f3dc6e171bf0ecf097ff7a0ffff7cb1"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:21a5e440dbe315ab9825fcd459b8814bb92b27c974cbc23c3e8baa2b76890077"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01dd777215e2aa86dfd664daed5957704b769e726626393438f9c87690ce78c3"}, - {file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4b06beb3b3f1479d32befd1f3079cc47b34fa2da62457cdf6c963393340b56e9"}, - {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:564d7922e4b13a16b98772441879fcdcbe82ff50daa622d681dd682175ea918c"}, - {file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0eb2a4f660fcd8e2b1c90ad566db2b98d7f3f4717c64fe0a83e0adb39766d5b8"}, - {file = "pydantic_core-2.18.4-cp312-none-win32.whl", hash = "sha256:8b8bab4c97248095ae0c4455b5a1cd1cdd96e4e4769306ab19dda135ea4cdb07"}, - {file = "pydantic_core-2.18.4-cp312-none-win_amd64.whl", hash = "sha256:14601cdb733d741b8958224030e2bfe21a4a881fb3dd6fbb21f071cabd48fa0a"}, - {file = "pydantic_core-2.18.4-cp312-none-win_arm64.whl", hash = "sha256:c1322d7dd74713dcc157a2b7898a564ab091ca6c58302d5c7b4c07296e3fd00f"}, - {file = "pydantic_core-2.18.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:823be1deb01793da05ecb0484d6c9e20baebb39bd42b5d72636ae9cf8350dbd2"}, - {file = "pydantic_core-2.18.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebef0dd9bf9b812bf75bda96743f2a6c5734a02092ae7f721c048d156d5fabae"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae1d6df168efb88d7d522664693607b80b4080be6750c913eefb77e34c12c71a"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9899c94762343f2cc2fc64c13e7cae4c3cc65cdfc87dd810a31654c9b7358cc"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99457f184ad90235cfe8461c4d70ab7dd2680e28821c29eca00252ba90308c78"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18f469a3d2a2fdafe99296a87e8a4c37748b5080a26b806a707f25a902c040a8"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cdf28938ac6b8b49ae5e92f2735056a7ba99c9b110a474473fd71185c1af5d"}, - {file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:938cb21650855054dc54dfd9120a851c974f95450f00683399006aa6e8abb057"}, - {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:44cd83ab6a51da80fb5adbd9560e26018e2ac7826f9626bc06ca3dc074cd198b"}, - {file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:972658f4a72d02b8abfa2581d92d59f59897d2e9f7e708fdabe922f9087773af"}, - {file = "pydantic_core-2.18.4-cp38-none-win32.whl", hash = "sha256:1d886dc848e60cb7666f771e406acae54ab279b9f1e4143babc9c2258213daa2"}, - {file = "pydantic_core-2.18.4-cp38-none-win_amd64.whl", hash = "sha256:bb4462bd43c2460774914b8525f79b00f8f407c945d50881568f294c1d9b4443"}, - {file = "pydantic_core-2.18.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:44a688331d4a4e2129140a8118479443bd6f1905231138971372fcde37e43528"}, - {file = "pydantic_core-2.18.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a2fdd81edd64342c85ac7cf2753ccae0b79bf2dfa063785503cb85a7d3593223"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86110d7e1907ab36691f80b33eb2da87d780f4739ae773e5fc83fb272f88825f"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46387e38bd641b3ee5ce247563b60c5ca098da9c56c75c157a05eaa0933ed154"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:123c3cec203e3f5ac7b000bd82235f1a3eced8665b63d18be751f115588fea30"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc1803ac5c32ec324c5261c7209e8f8ce88e83254c4e1aebdc8b0a39f9ddb443"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53db086f9f6ab2b4061958d9c276d1dbe3690e8dd727d6abf2321d6cce37fa94"}, - {file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abc267fa9837245cc28ea6929f19fa335f3dc330a35d2e45509b6566dc18be23"}, - {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a0d829524aaefdebccb869eed855e2d04c21d2d7479b6cada7ace5448416597b"}, - {file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:509daade3b8649f80d4e5ff21aa5673e4ebe58590b25fe42fac5f0f52c6f034a"}, - {file = "pydantic_core-2.18.4-cp39-none-win32.whl", hash = "sha256:ca26a1e73c48cfc54c4a76ff78df3727b9d9f4ccc8dbee4ae3f73306a591676d"}, - {file = "pydantic_core-2.18.4-cp39-none-win_amd64.whl", hash = "sha256:c67598100338d5d985db1b3d21f3619ef392e185e71b8d52bceacc4a7771ea7e"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:574d92eac874f7f4db0ca653514d823a0d22e2354359d0759e3f6a406db5d55d"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1f4d26ceb5eb9eed4af91bebeae4b06c3fb28966ca3a8fb765208cf6b51102ab"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77450e6d20016ec41f43ca4a6c63e9fdde03f0ae3fe90e7c27bdbeaece8b1ed4"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d323a01da91851a4f17bf592faf46149c9169d68430b3146dcba2bb5e5719abc"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43d447dd2ae072a0065389092a231283f62d960030ecd27565672bd40746c507"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:578e24f761f3b425834f297b9935e1ce2e30f51400964ce4801002435a1b41ef"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:81b5efb2f126454586d0f40c4d834010979cb80785173d1586df845a632e4e6d"}, - {file = "pydantic_core-2.18.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ab86ce7c8f9bea87b9d12c7f0af71102acbf5ecbc66c17796cff45dae54ef9a5"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:90afc12421df2b1b4dcc975f814e21bc1754640d502a2fbcc6d41e77af5ec312"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:51991a89639a912c17bef4b45c87bd83593aee0437d8102556af4885811d59f5"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:293afe532740370aba8c060882f7d26cfd00c94cae32fd2e212a3a6e3b7bc15e"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48ece5bde2e768197a2d0f6e925f9d7e3e826f0ad2271120f8144a9db18d5c8"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eae237477a873ab46e8dd748e515c72c0c804fb380fbe6c85533c7de51f23a8f"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:834b5230b5dfc0c1ec37b2fda433b271cbbc0e507560b5d1588e2cc1148cf1ce"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e858ac0a25074ba4bce653f9b5d0a85b7456eaddadc0ce82d3878c22489fa4ee"}, - {file = "pydantic_core-2.18.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2fd41f6eff4c20778d717af1cc50eca52f5afe7805ee530a4fbd0bae284f16e9"}, - {file = "pydantic_core-2.18.4.tar.gz", hash = "sha256:ec3beeada09ff865c344ff3bc2f427f5e6c26401cc6113d77e372c3fdac73864"}, + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, + {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, ] [package.dependencies] @@ -367,13 +392,13 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no [[package]] name = "pytest-asyncio" -version = "0.23.7" +version = "0.23.8" description = "Pytest support for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "pytest_asyncio-0.23.7-py3-none-any.whl", hash = "sha256:009b48127fbe44518a547bddd25611551b0e43ccdbf1e67d12479f569832c20b"}, - {file = "pytest_asyncio-0.23.7.tar.gz", hash = "sha256:5f5c72948f4c49e7db4f29f2521d4031f1c27f86e57b046126654083d4770268"}, + {file = "pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"}, + {file = "pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"}, ] [package.dependencies] @@ -397,15 +422,42 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "ruff" +version = "0.5.7" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.5.7-py3-none-linux_armv6l.whl", hash = "sha256:548992d342fc404ee2e15a242cdbea4f8e39a52f2e7752d0e4cbe88d2d2f416a"}, + {file = "ruff-0.5.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:00cc8872331055ee017c4f1071a8a31ca0809ccc0657da1d154a1d2abac5c0be"}, + {file = "ruff-0.5.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eaf3d86a1fdac1aec8a3417a63587d93f906c678bb9ed0b796da7b59c1114a1e"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a01c34400097b06cf8a6e61b35d6d456d5bd1ae6961542de18ec81eaf33b4cb8"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcc8054f1a717e2213500edaddcf1dbb0abad40d98e1bd9d0ad364f75c763eea"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f70284e73f36558ef51602254451e50dd6cc479f8b6f8413a95fcb5db4a55fc"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a78ad870ae3c460394fc95437d43deb5c04b5c29297815a2a1de028903f19692"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ccd078c66a8e419475174bfe60a69adb36ce04f8d4e91b006f1329d5cd44bcf"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e31c9bad4ebf8fdb77b59cae75814440731060a09a0e0077d559a556453acbb"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d796327eed8e168164346b769dd9a27a70e0298d667b4ecee6877ce8095ec8e"}, + {file = "ruff-0.5.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a09ea2c3f7778cc635e7f6edf57d566a8ee8f485f3c4454db7771efb692c499"}, + {file = "ruff-0.5.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a36d8dcf55b3a3bc353270d544fb170d75d2dff41eba5df57b4e0b67a95bb64e"}, + {file = "ruff-0.5.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9369c218f789eefbd1b8d82a8cf25017b523ac47d96b2f531eba73770971c9e5"}, + {file = "ruff-0.5.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b88ca3db7eb377eb24fb7c82840546fb7acef75af4a74bd36e9ceb37a890257e"}, + {file = "ruff-0.5.7-py3-none-win32.whl", hash = "sha256:33d61fc0e902198a3e55719f4be6b375b28f860b09c281e4bdbf783c0566576a"}, + {file = "ruff-0.5.7-py3-none-win_amd64.whl", hash = "sha256:083bbcbe6fadb93cd86709037acc510f86eed5a314203079df174c40bbbca6b3"}, + {file = "ruff-0.5.7-py3-none-win_arm64.whl", hash = "sha256:2dca26154ff9571995107221d0aeaad0e75a77b5a682d6236cf89a58c70b76f4"}, + {file = "ruff-0.5.7.tar.gz", hash = "sha256:8dfc0a458797f5d9fb622dd0efc52d796f23f0a1493a9527f4e49a550ae9a7e5"}, +] + [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] @@ -421,24 +473,54 @@ files = [ [[package]] name = "tomli" -version = "2.0.1" +version = "2.2.1" description = "A lil' TOML parser" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, - {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] name = "types-python-dateutil" -version = "2.9.0.20240316" +version = "2.9.0.20241206" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.8" files = [ - {file = "types-python-dateutil-2.9.0.20240316.tar.gz", hash = "sha256:5d2f2e240b86905e40944dd787db6da9263f0deabef1076ddaed797351ec0202"}, - {file = "types_python_dateutil-2.9.0.20240316-py3-none-any.whl", hash = "sha256:6b8cb66d960771ce5ff974e9dd45e38facb81718cc1e208b10b1baccbfdbee3b"}, + {file = "types_python_dateutil-2.9.0.20241206-py3-none-any.whl", hash = "sha256:e248a4bc70a486d3e3ec84d0dc30eec3a5f979d6e7ee4123ae043eedbb987f53"}, + {file = "types_python_dateutil-2.9.0.20241206.tar.gz", hash = "sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb"}, ] [[package]] @@ -455,4 +537,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "7fa2085bd251148908cf9a89f13b158fe85ccb037bb44614ae5f150ceecee53c" +content-hash = "6f6c191c1028d17a97fdfa84cedfd3cef94b5d63d98b8c1d333b3398eeea9055" diff --git a/pyproject.toml b/pyproject.toml index ca24275..66a8846 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "webflow" -version = "1.2.2" +version = "1.2.1" description = "" readme = "README.md" authors = [] @@ -34,6 +34,7 @@ Repository = 'https://github.com/webflow/webflow-python' python = "^3.8" httpx = ">=0.21.2" pydantic = ">= 1.9.2" +pydantic-core = "^2.18.2" typing_extensions = ">= 4.0.0" [tool.poetry.dev-dependencies] @@ -42,6 +43,7 @@ pytest = "^7.4.0" pytest-asyncio = "^0.23.5" python-dateutil = "^2.9.0" types-python-dateutil = "^2.9.0.20240316" +ruff = "^0.5.6" [tool.pytest.ini_options] testpaths = [ "tests" ] @@ -50,6 +52,9 @@ asyncio_mode = "auto" [tool.mypy] plugins = ["pydantic.mypy"] +[tool.ruff] +line-length = 120 + [build-system] requires = ["poetry-core"] diff --git a/reference.md b/reference.md index 5110fae..5001bba 100644 --- a/reference.md +++ b/reference.md @@ -12,7 +12,9 @@
-Information about the Authorized User

Required Scope | `authorized_user:read` +Information about the Authorized User + +Required Scope | `authorized_user:read`
@@ -27,7 +29,7 @@ Information about the Authorized User

Required Scope | `authorized_user
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -72,7 +74,9 @@ client.token.authorized_by()
-Information about the authorization token
Access to this endpoint requires a bearer token from a Data Client App.
+Information about the authorization token + +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients).
@@ -87,7 +91,7 @@ Information about the authorization token
## Sites -
client.sites.list() +
client.sites.create(...)
@@ -133,7 +137,9 @@ client.token.introspect()
-List of all sites the provided access token is able to access.

Required scope | `sites:read` +Create a site. This endpoint requires an Enterprise workspace. + +Required scope | `workspace:write`
@@ -148,12 +154,15 @@ List of all sites the provided access token is able to access.

Requir
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.list() +client.sites.create( + workspace_id="580e63e98c9a982ac9b8b741", + name="The Hitchhiker's Guide to the Galaxy", +) ```
@@ -169,6 +178,38 @@ client.sites.list()
+**workspace_id:** `str` — Unique identifier for a Workspace + +
+
+ +
+
+ +**name:** `str` — The name of the site + +
+
+ +
+
+ +**template_name:** `typing.Optional[str]` — The workspace or marketplace template to use + +
+
+ +
+
+ +**parent_folder_id:** `typing.Optional[str]` — MegaDodo Publications - Potential Book Ideas + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -181,7 +222,7 @@ client.sites.list()
-
client.sites.get(...) +
client.sites.list()
@@ -193,7 +234,9 @@ client.sites.list()
-Get a site by site id

Required scope | `sites:read` +List of all sites the provided access token is able to access. + +Required scope | `sites:read`
@@ -208,14 +251,12 @@ Get a site by site id

Required scope | `sites:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.get( - site_id="site_id", -) +client.sites.list() ```
@@ -231,14 +272,6 @@ client.sites.get(
-**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -251,7 +284,7 @@ client.sites.get(
-
client.sites.get_custom_domain(...) +
client.sites.get(...)
@@ -263,7 +296,9 @@ client.sites.get(
-Get a list of all custom domains related to site.

Required scope | `sites:read` +Get details of a site. + +Required scope | `sites:read`
@@ -278,13 +313,13 @@ Get a list of all custom domains related to site.

Required scope | `s
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.get_custom_domain( - site_id="site_id", +client.sites.get( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -321,7 +356,7 @@ client.sites.get_custom_domain(
-
client.sites.publish(...) +
client.sites.delete(...)
@@ -333,7 +368,9 @@ client.sites.get_custom_domain(
-Publish a site to one more more domains.

Required scope | `sites:write` +Delete a site. This endpoint requires an Enterprise workspace. + +Required scope | `sites:write`
@@ -348,13 +385,13 @@ Publish a site to one more more domains.

Required scope | `sites:writ
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.publish( - site_id="site_id", +client.sites.delete( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -379,22 +416,6 @@ client.sites.publish(
-**custom_domains:** `typing.Optional[typing.Sequence[str]]` — Array of Custom Domain ids to publish - -
-
- -
-
- -**publish_to_webflow_subdomain:** `typing.Optional[bool]` — Choice of whether to publish to the default Webflow Subdomain - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -407,8 +428,7 @@ client.sites.publish(
-## Sites ActivityLogs -
client.sites.activity_logs.list(...) +
client.sites.update(...)
@@ -420,7 +440,9 @@ client.sites.publish(
-Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` +Update a site. This endpoint requires an Enterprise workspace. + +Required scope | `sites:write`
@@ -435,13 +457,13 @@ Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.activity_logs.list( - site_id="site_id", +client.sites.update( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -466,7 +488,7 @@ client.sites.activity_logs.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**name:** `typing.Optional[str]` — The name of the site
@@ -474,7 +496,7 @@ client.sites.activity_logs.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**parent_folder_id:** `typing.Optional[str]` — The parent folder ID of the site
@@ -494,8 +516,7 @@ client.sites.activity_logs.list(
-## Collections -
client.collections.list(...) +
client.sites.get_custom_domain(...)
@@ -507,7 +528,9 @@ client.sites.activity_logs.list(
-List of all Collections within a Site.

Required scope | `cms:read` +Get a list of all custom domains related to site. + +Required scope | `sites:read`
@@ -522,13 +545,13 @@ List of all Collections within a Site.

Required scope | `cms:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.list( - site_id="site_id", +client.sites.get_custom_domain( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -565,7 +588,7 @@ client.collections.list(
-
client.collections.create(...) +
client.sites.publish(...)
@@ -577,7 +600,11 @@ client.collections.list(
-Create a Collection for a site.

Required scope | `cms:write` +Publishes a site to one or more more domains. + +This endpoint has a limit of one successful publish queue per minute. + +Required scope | `sites:write`
@@ -592,16 +619,13 @@ Create a Collection for a site.

Required scope | `cms:write`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.create( - site_id="site_id", - display_name="Blog Posts", - singular_name="Blog Post", - slug="posts", +client.sites.publish( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -626,15 +650,7 @@ client.collections.create(
-**display_name:** `str` — Name of the collection. Each collection name must be distinct. - -
-
- -
-
- -**singular_name:** `str` — Singular name of each item. +**custom_domains:** `typing.Optional[typing.Sequence[str]]` — Array of Custom Domain IDs to publish
@@ -642,7 +658,7 @@ client.collections.create(
-**slug:** `typing.Optional[str]` — Part of a URL that identifier +**publish_to_webflow_subdomain:** `typing.Optional[bool]` — Choice of whether to publish to the default Webflow Subdomain
@@ -662,7 +678,8 @@ client.collections.create(
-
client.collections.get(...) +## Collections +
client.collections.list(...)
@@ -674,7 +691,9 @@ client.collections.create(
-Get the full details of a collection from its ID.

Required scope | `cms:read` +List of all Collections within a Site. + +Required scope | `cms:read`
@@ -689,13 +708,13 @@ Get the full details of a collection from its ID.

Required scope | `c
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.get( - collection_id="collection_id", +client.collections.list( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -712,7 +731,7 @@ client.collections.get(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -732,7 +751,7 @@ client.collections.get(
-
client.collections.delete_collection(...) +
client.collections.create(...)
@@ -744,7 +763,9 @@ client.collections.get(
-Delete a collection using its ID.

Required scope | `cms:write` +Create a Collection for a site. + +Required scope | `cms:write`
@@ -759,13 +780,16 @@ Delete a collection using its ID.

Required scope | `cms:write`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.delete_collection( - collection_id="collection_id", +client.collections.create( + site_id="580e63e98c9a982ac9b8b741", + display_name="Blog Posts", + singular_name="Blog Post", + slug="posts", ) ``` @@ -782,7 +806,31 @@ client.collections.delete_collection(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**display_name:** `str` — Name of the collection. Each collection name must be distinct. + +
+
+ +
+
+ +**singular_name:** `str` — Singular name of each item. + +
+
+ +
+
+ +**slug:** `typing.Optional[str]` — Part of a URL that identifier
@@ -802,7 +850,7 @@ client.collections.delete_collection(
-
client.collections.delete(...) +
client.collections.get(...)
@@ -814,7 +862,9 @@ client.collections.delete_collection(
-Delete a custom field in a collection. This endpoint does not currently support bulk deletion.

Required scope | `cms:write` +Get the full details of a collection from its ID. + +Required scope | `cms:read`
@@ -829,14 +879,13 @@ Delete a custom field in a collection. This endpoint does not currently support
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.delete( - collection_id="collection_id", - field_id="field_id", +client.collections.get( + collection_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -861,14 +910,6 @@ client.collections.delete(
-**field_id:** `str` — Unique identifier for a Field in a collection - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -881,8 +922,7 @@ client.collections.delete(
-## Collections Fields -
client.collections.fields.create(...) +
client.collections.delete(...)
@@ -894,7 +934,9 @@ client.collections.delete(
-Create a custom field in a collection.

Slugs must be all lowercase letters without spaces. If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will convert the slug to lowercase and replace spaces with "-."

Only some field types can be created through the API. This endpoint does not currently support bulk creation.

Required scope | `cms:write` +Delete a collection using its ID. + +Required scope | `cms:write`
@@ -909,18 +951,13 @@ Create a custom field in a collection.

Slugs must be all lowercase le
```python -from webflow.client import Webflow -from webflow.resources.collections import FieldCreateType +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.fields.create( - collection_id="collection_id", - is_required=False, - type=FieldCreateType.RICH_TEXT, - display_name="Post Body", - help_text="Add the body of your post here", +client.collections.delete( + collection_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -945,38 +982,6 @@ client.collections.fields.create(
-**type:** `FieldCreateType` — Choose these appropriate field type for your collection data - -
-
- -
-
- -**display_name:** `str` — The name of a field - -
-
- -
-
- -**is_required:** `typing.Optional[bool]` — define whether a field is required in a collection - -
-
- -
-
- -**help_text:** `typing.Optional[str]` — Additional text to help anyone filling out this field - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -989,7 +994,8 @@ client.collections.fields.create(
-
client.collections.fields.update(...) +## Pages +
client.pages.list(...)
@@ -1001,7 +1007,9 @@ client.collections.fields.create(
-Update a custom field in a collection.

Required scope | `cms:write` +List of all pages for a site. + +Required scope | `pages:read`
@@ -1016,17 +1024,14 @@ Update a custom field in a collection.

Required scope | `cms:write`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.fields.update( - collection_id="collection_id", - field_id="field_id", - is_required=False, - display_name="Post Body", - help_text="Add the body of your post here", +client.pages.list( + site_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", ) ``` @@ -1043,15 +1048,7 @@ client.collections.fields.update(
-**collection_id:** `str` — Unique identifier for a Collection - -
-
- -
-
- -**field_id:** `str` — Unique identifier for a Field in a collection +**site_id:** `str` — Unique identifier for a Site
@@ -1059,7 +1056,7 @@ client.collections.fields.update(
-**is_required:** `typing.Optional[bool]` — Define whether a field is required in a collection +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization.
@@ -1067,7 +1064,7 @@ client.collections.fields.update(
-**display_name:** `typing.Optional[str]` — The name of a field +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -1075,7 +1072,7 @@ client.collections.fields.update(
-**help_text:** `typing.Optional[str]` — Additional text to help anyone filling out this field +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -1095,8 +1092,7 @@ client.collections.fields.update(
-## Collections Items -
client.collections.items.list_items(...) +
client.pages.get_metadata(...)
@@ -1108,7 +1104,9 @@ client.collections.fields.update(
-List of all Items within a Collection.

Required scope | `CMS:read` +Get metadata information for a single page. + +Required scope | `pages:read`
@@ -1123,13 +1121,14 @@ List of all Items within a Collection.

Required scope | `CMS:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.list_items( - collection_id="collection_id", +client.pages.get_metadata( + page_id="63c720f9347c2139b248e552", + locale_id="65427cf400e02b306eaa04a0", ) ``` @@ -1146,7 +1145,7 @@ client.collections.items.list_items(
-**collection_id:** `str` — Unique identifier for a Collection +**page_id:** `str` — Unique identifier for a Page
@@ -1154,7 +1153,7 @@ client.collections.items.list_items(
-**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization.
@@ -1162,47 +1161,1226 @@ client.collections.items.list_items(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
-
-
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) -
+
+
client.pages.update_page_settings(...)
-**name:** `typing.Optional[str]` — The name of the item(s) - -
-
+#### 📝 Description
-**slug:** `typing.Optional[str]` — The slug of the item - -
-
-
-**sort_by:** `typing.Optional[ItemsListItemsRequestSortBy]` — Sort results by the provided value - +Update Page-level metadata, including SEO and Open Graph fields. + +Required scope | `pages:write` +
+
-
+#### 🔌 Usage + +
+
+ +
+
+ +```python +import datetime + +from webflow import PageOpenGraph, PageSeo, Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.update_page_settings( + page_id="63c720f9347c2139b248e552", + locale_id="65427cf400e02b306eaa04a0", + id="6596da6045e56dee495bcbba", + site_id="6258612d1ee792848f805dcf", + title="Guide to the Galaxy", + slug="guide-to-the-galaxy", + created_on=datetime.datetime.fromisoformat( + "2024-03-11 10:42:00+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2024-03-11 10:42:42+00:00", + ), + archived=False, + draft=False, + can_branch=True, + is_branch=False, + seo=PageSeo( + title="The Ultimate Hitchhiker's Guide to the Galaxy", + description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", + ), + open_graph=PageOpenGraph( + title="Explore the Cosmos with The Ultimate Guide", + title_copied=False, + description="Dive deep into the mysteries of the universe with your guide to everything galactic.", + description_copied=False, + ), + page_locale_id="653fd9af6a07fc9cfd7a5e57", + published_path="/en-us/guide-to-the-galaxy", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**id:** `str` — Unique identifier for the Page + +
+
+ +
+
+ +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. + +
+
+ +
+
+ +**site_id:** `typing.Optional[str]` — Unique identifier for the Site + +
+
+ +
+
+ +**title:** `typing.Optional[str]` — Title of the Page + +
+
+ +
+
+ +**slug:** `typing.Optional[str]` — slug of the Page (derived from title) + +
+
+ +
+
+ +**parent_id:** `typing.Optional[str]` — Identifier of the parent folder + +
+
+ +
+
+ +**collection_id:** `typing.Optional[str]` — Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. + +
+
+ +
+
+ +**created_on:** `typing.Optional[dt.datetime]` — The date the Page was created + +
+
+ +
+
+ +**last_updated:** `typing.Optional[dt.datetime]` — The date the Page was most recently updated + +
+
+ +
+
+ +**archived:** `typing.Optional[bool]` — Whether the Page has been archived + +
+
+ +
+
+ +**draft:** `typing.Optional[bool]` — Whether the Page is a draft + +
+
+ +
+
+ +**can_branch:** `typing.Optional[bool]` — Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) + +
+
+ +
+
+ +**is_branch:** `typing.Optional[bool]` — Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) + +
+
+ +
+
+ +**is_members_only:** `typing.Optional[bool]` — Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) + +
+
+ +
+
+ +**seo:** `typing.Optional[PageSeo]` — SEO-related fields for the Page + +
+
+ +
+
+ +**open_graph:** `typing.Optional[PageOpenGraph]` — Open Graph fields for the Page + +
+
+ +
+
+ +**page_locale_id:** `typing.Optional[str]` — Unique ID of the page locale + +
+
+ +
+
+ +**published_path:** `typing.Optional[str]` — Relative path of the published page URL + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + + +
+
+ +
client.pages.get_content(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get static content from a static page. This includes text nodes, image nodes and component instances. +To retrieve the contents of components in the page use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint. + +If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + +Required scope | `pages:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.get_content( + page_id="63c720f9347c2139b248e552", + locale_id="65427cf400e02b306eaa04a0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.pages.update_static_content(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +This endpoint updates content on a static page in **secondary locales**. It supports updating up to 1000 nodes in a single request. + +Before making updates: +1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) endpoint to identify available content nodes and their types +2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint + + + This endpoint is specifically for localized pages. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + +Required scope | `pages:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import ( + ComponentInstanceNodePropertyOverridesWrite, + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + TextNodeWrite, + Webflow, +) + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.update_static_content( + page_id="63c720f9347c2139b248e552", + locale_id="localeId", + nodes=[ + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", + text="

The Hitchhiker's Guide to the Galaxy

", + ), + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + ComponentInstanceNodePropertyOverridesWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + property_overrides=[ + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", + text="

Time is an illusion

", + ), + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", + text="Life, the Universe and Everything", + ), + ], + ), + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**locale_id:** `str` — The locale identifier. + +
+
+ +
+
+ +**nodes:** `typing.Sequence[PageDomWriteNodesItem]` — List of DOM Nodes with the new content that will be updated in each node. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Components +
client.components.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List of all components for a site. + +Required scope | `components:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.components.list( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.components.get_content(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get static content from a component definition. This includes text nodes, image nodes and nested component instances. +To retrieve dynamic content set by component properties, use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + +If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + +Required scope | `components:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.components.get_content( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**component_id:** `str` — Unique identifier for a Component + +
+
+ +
+
+ +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.components.update_content(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +This endpoint updates content within a component defintion for **secondary locales**. It supports updating up to 1000 nodes in a single request. + +Before making updates: +1. Use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint to identify available content nodes and their types +2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint + + + This endpoint is specifically for localizing component definitions. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + +Required scope | `components:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import ( + ComponentInstanceNodePropertyOverridesWrite, + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + TextNodeWrite, + Webflow, +) + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.components.update_content( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + nodes=[ + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", + text="

The Hitchhiker's Guide to the Galaxy

", + ), + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + ComponentInstanceNodePropertyOverridesWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + property_overrides=[ + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", + text="

Time is an illusion

", + ), + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", + text="Life, the Universe and Everything", + ), + ], + ), + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**component_id:** `str` — Unique identifier for a Component + +
+
+ +
+
+ +**nodes:** `typing.Sequence[ComponentDomWriteNodesItem]` — List of DOM Nodes with the new content that will be updated in each node. + +
+
+ +
+
+ +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.components.get_properties(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get the property default values of a component definition. + +If you do not provide a Locale ID in your request, the response will return any properties that can be localized from the Primary locale. + +Required scope | `components:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.components.get_properties( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**component_id:** `str` — Unique identifier for a Component + +
+
+ +
+
+ +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.components.update_properties(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update the property default values of a component definition in a specificed locale. + +Before making updates: +1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify available properties + +The request requires a secondary locale ID. If a locale is missing, the request will not be processed and will result in an error. + +Required scope | `components:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow +from webflow.resources.components import ComponentPropertiesWritePropertiesItem + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.components.update_properties( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + properties=[ + ComponentPropertiesWritePropertiesItem( + property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", + text="The Hitchhiker’s Guide to the Galaxy", + ), + ComponentPropertiesWritePropertiesItem( + property_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Dont Panic!

Always know where your towel is.

", + ), + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**component_id:** `str` — Unique identifier for a Component + +
+
+ +
+
+ +**properties:** `typing.Sequence[ComponentPropertiesWritePropertiesItem]` — A list of component properties to update within the specified secondary locale. + +
+
+ +
+
+ +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Scripts +
client.scripts.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +List of scripts registered to a Site. + +In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered +to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate +`custom_code` endpoints. +Additionally, Scripts can be remotely hosted, or registered as inline snippets. + +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + +Required scope | `custom_code:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.scripts.list( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.scripts.register_hosted(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Add a script to a Site's Custom Code registry. + +In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered +to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate +`custom_code` endpoints. +Additionally, Scripts can be remotely hosted, or registered as inline snippets. + +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + +Required scope | `custom_code:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.scripts.register_hosted( + site_id="580e63e98c9a982ac9b8b741", + hosted_location="hostedLocation", + integrity_hash="integrityHash", + version="version", + display_name="displayName", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
-**sort_order:** `typing.Optional[ItemsListItemsRequestSortOrder]` — Sorts the results by asc or desc +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**hosted_location:** `str` — URI for an externally hosted script location + +
+
+ +
+
+ +**integrity_hash:** `str` — Sub-Resource Integrity Hash + +
+
+ +
+
+ +**version:** `str` — A Semantic Version (SemVer) string, denoting the version of the script + +
+
+ +
+
+ +**display_name:** `str` — User-facing name for the script. Must be between 1 and 50 alphanumeric characters + +
+
+ +
+
+ +**can_copy:** `typing.Optional[bool]` — Define whether the script can be copied on site duplication and transfer
@@ -1222,7 +2400,7 @@ client.collections.items.list_items(
-
client.collections.items.create_item(...) +
client.scripts.register_inline(...)
@@ -1234,7 +2412,15 @@ client.collections.items.list_items(
-Create Item in a Collection.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` +Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters. + +In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered +to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate +`custom_code` endpoints. + +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + +Required scope | `custom_code:write`
@@ -1249,25 +2435,16 @@ Create Item in a Collection.

To create items across multiple locales,
```python -from webflow import CollectionItemFieldData -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.create_item( - collection_id="collection_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), +client.scripts.register_inline( + site_id="580e63e98c9a982ac9b8b741", + source_code="alert('hello world');", + version="0.0.1", + display_name="Alert", ) ``` @@ -1284,7 +2461,7 @@ client.collections.items.create_item(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -1292,7 +2469,7 @@ client.collections.items.create_item(
-**id:** `str` — Unique identifier for the Item +**source_code:** `str` — The code to be added to the site (to be hosted by Webflow).
@@ -1300,7 +2477,7 @@ client.collections.items.create_item(
-**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item +**version:** `str` — A Semantic Version (SemVer) string, denoting the version of the script
@@ -1308,7 +2485,7 @@ client.collections.items.create_item(
-**last_published:** `typing.Optional[str]` — The date the item was last published +**display_name:** `str` — User-facing name for the script. Must be between 1 and 50 alphanumeric characters
@@ -1316,7 +2493,7 @@ client.collections.items.create_item(
-**last_updated:** `typing.Optional[str]` — The date the item was last updated +**integrity_hash:** `typing.Optional[str]` — Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation)
@@ -1324,7 +2501,7 @@ client.collections.items.create_item(
-**created_on:** `typing.Optional[str]` — The date the item was created +**can_copy:** `typing.Optional[bool]` — Define whether the script can be copied on site duplication and transfer
@@ -1332,23 +2509,72 @@ client.collections.items.create_item(
-**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+ + + +
+ +## Assets +
client.assets.list(...)
-**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft - +#### 📝 Description + +
+
+ +
+
+ +List assets for a given site + +Required scope | `assets:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.list( + site_id="580e63e98c9a982ac9b8b741", +) + +```
+
+
+ +#### ⚙️ Parameters
-**field_data:** `typing.Optional[CollectionItemFieldData]` +
+
+ +**site_id:** `str` — Unique identifier for a Site
@@ -1368,7 +2594,7 @@ client.collections.items.create_item(
-
client.collections.items.list_items_live(...) +
client.assets.create(...)
@@ -1380,7 +2606,15 @@ client.collections.items.create_item(
-List of all live Items within a Collection.

Required scope | `CMS:read` +Create a new asset entry. + + +This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. +You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) +request to the `uploadUrl` with the `uploadDetails` object as your header information in the request. + + +Required scope | `assets:write`
@@ -1395,13 +2629,15 @@ List of all live Items within a Collection.

Required scope | `CMS:rea
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.list_items_live( - collection_id="collection_id", +client.assets.create( + site_id="580e63e98c9a982ac9b8b741", + file_name="file.png", + file_hash="3c7d87c9575702bc3b1e991f4d3c638e", ) ``` @@ -1418,7 +2654,7 @@ client.collections.items.list_items_live(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -1426,7 +2662,7 @@ client.collections.items.list_items_live(
-**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. +**file_name:** `str` — File name including file extension. File names must be less than 100 characters.
@@ -1434,7 +2670,7 @@ client.collections.items.list_items_live(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**file_hash:** `str` — MD5 hash of the file
@@ -1442,7 +2678,7 @@ client.collections.items.list_items_live(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**parent_folder:** `typing.Optional[str]` — ID of the Asset folder (optional)
@@ -1450,31 +2686,71 @@ client.collections.items.list_items_live(
-**name:** `typing.Optional[str]` — The name of the item(s) +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+ + + + +
+
client.assets.get(...)
-**slug:** `typing.Optional[str]` — The slug of the item - +#### 📝 Description + +
+
+ +
+
+ +Get an Asset + +Required scope | `assets:read`
+
+
+ +#### 🔌 Usage
-**sort_by:** `typing.Optional[ItemsListItemsLiveRequestSortBy]` — Sort results by the provided value - +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.get( + asset_id="580e63fc8c9a982ac9b8b745", +) + +``` +
+
+#### ⚙️ Parameters +
-**sort_order:** `typing.Optional[ItemsListItemsLiveRequestSortOrder]` — Sorts the results by asc or desc +
+
+ +**asset_id:** `str` — Unique identifier for an Asset on a site
@@ -1494,7 +2770,7 @@ client.collections.items.list_items_live(
-
client.collections.items.create_item_live(...) +
client.assets.delete(...)
@@ -1506,7 +2782,9 @@ client.collections.items.list_items_live(
-Create live Item in a Collection. This Item will be published to the live site.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` +Delete an Asset + +Required Scope: `assets: write`
@@ -1521,25 +2799,13 @@ Create live Item in a Collection. This Item will be published to the live site.
```python -from webflow import CollectionItemFieldData -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.create_item_live( - collection_id="collection_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), +client.assets.delete( + asset_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -1556,7 +2822,7 @@ client.collections.items.create_item_live(
-**collection_id:** `str` — Unique identifier for a Collection +**asset_id:** `str` — Unique identifier for an Asset on a site
@@ -1564,47 +2830,71 @@ client.collections.items.create_item_live(
-**id:** `str` — Unique identifier for the Item +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
-
-
-**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item -
+
+
client.assets.update(...)
-**last_published:** `typing.Optional[str]` — The date the item was last published - -
-
+#### 📝 Description
-**last_updated:** `typing.Optional[str]` — The date the item was last updated - +
+
+ +Update an Asset + +Required scope | `assets:write`
+
+
+ +#### 🔌 Usage
-**created_on:** `typing.Optional[str]` — The date the item was created - +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.update( + asset_id="580e63fc8c9a982ac9b8b745", +) + +``` +
+
+#### ⚙️ Parameters +
-**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived +
+
+ +**asset_id:** `str` — Unique identifier for an Asset on a site
@@ -1612,7 +2902,7 @@ client.collections.items.create_item_live(
-**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft +**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization.
@@ -1620,7 +2910,7 @@ client.collections.items.create_item_live(
-**field_data:** `typing.Optional[CollectionItemFieldData]` +**display_name:** `typing.Optional[str]` — A human readable name for the asset
@@ -1640,7 +2930,7 @@ client.collections.items.create_item_live(
-
client.collections.items.create_item_for_multiple_locales(...) +
client.assets.list_folders(...)
@@ -1652,7 +2942,9 @@ client.collections.items.create_item_live(
-Create single Item in a Collection with multiple corresponding locales.

Required scope | `CMS:write` +List Asset Folders within a given site + +Required scope | `assets:read`
@@ -1667,14 +2959,13 @@ Create single Item in a Collection with multiple corresponding locales.
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.create_item_for_multiple_locales( - collection_id="collection_id", - id="580e64008c9a982ac9b8b754", +client.assets.list_folders( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -1691,7 +2982,7 @@ client.collections.items.create_item_for_multiple_locales(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -1699,47 +2990,72 @@ client.collections.items.create_item_for_multiple_locales(
-**id:** `str` — Unique identifier for the Item +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+ +
-
-
-**cms_locale_ids:** `typing.Optional[typing.Sequence[str]]` — Array of identifiers for the locales where the item will be created -
+
+
client.assets.create_folder(...)
-**last_published:** `typing.Optional[str]` — The date the item was last published - -
-
+#### 📝 Description
-**last_updated:** `typing.Optional[str]` — The date the item was last updated - +
+
+ +Create an Asset Folder within a given site + +Required scope | `assets:write` +
+
+#### 🔌 Usage +
-**created_on:** `typing.Optional[str]` — The date the item was created - +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.assets.create_folder( + site_id="580e63e98c9a982ac9b8b741", + display_name="my asset folder", +) + +```
+
+
+ +#### ⚙️ Parameters
-**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived +
+
+ +**site_id:** `str` — Unique identifier for a Site
@@ -1747,7 +3063,7 @@ client.collections.items.create_item_for_multiple_locales(
-**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft +**display_name:** `str` — A human readable name for the Asset Folder
@@ -1755,7 +3071,7 @@ client.collections.items.create_item_for_multiple_locales(
-**field_data:** `typing.Optional[BulkCollectionItemFieldData]` +**parent_folder:** `typing.Optional[str]` — An (optional) pointer to a parent Asset Folder (or null for root)
@@ -1775,7 +3091,7 @@ client.collections.items.create_item_for_multiple_locales(
-
client.collections.items.get_item(...) +
client.assets.get_folder(...)
@@ -1787,7 +3103,9 @@ client.collections.items.create_item_for_multiple_locales(
-Get details of a selected Collection Item.

Required scope | `CMS:read` +Get details about a specific Asset Folder + +Required scope | `assets:read`
@@ -1802,14 +3120,13 @@ Get details of a selected Collection Item.

Required scope | `CMS:read
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.get_item( - collection_id="collection_id", - item_id="item_id", +client.assets.get_folder( + asset_folder_id="6390c49774a71f0e3c1a08ee", ) ``` @@ -1826,23 +3143,7 @@ client.collections.items.get_item(
-**collection_id:** `str` — Unique identifier for a Collection - -
-
- -
-
- -**item_id:** `str` — Unique identifier for an Item - -
-
- -
-
- -**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. +**asset_folder_id:** `str` — Unique identifier for an Asset Folder
@@ -1862,7 +3163,8 @@ client.collections.items.get_item(
-
client.collections.items.delete_item(...) +## Webhooks +
client.webhooks.list(...)
@@ -1874,7 +3176,9 @@ client.collections.items.get_item(
-Delete an Item from a Collection. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` +List all App-created Webhooks registered for a given site + +Required scope | `sites:read`
@@ -1889,14 +3193,13 @@ Delete an Item from a Collection. This endpoint does not currently support bulk
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.delete_item( - collection_id="collection_id", - item_id="item_id", +client.webhooks.list( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -1913,23 +3216,7 @@ client.collections.items.delete_item(
-**collection_id:** `str` — Unique identifier for a Collection - -
-
- -
-
- -**item_id:** `str` — Unique identifier for an Item - -
-
- -
-
- -**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. +**site_id:** `str` — Unique identifier for a Site
@@ -1949,7 +3236,7 @@ client.collections.items.delete_item(
-
client.collections.items.update_item(...) +
client.webhooks.create(...)
@@ -1961,7 +3248,12 @@ client.collections.items.delete_item(
-Update a selected Item in a Collection.

Required scope | `CMS:write` +Create a new Webhook. + +Limit of 75 registrations per `triggerType`, per site. + +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). +Required scope | `sites:write`
@@ -1976,25 +3268,25 @@ Update a selected Item in a Collection.

Required scope | `CMS:write`
```python -from webflow import CollectionItemFieldData -from webflow.client import Webflow +import datetime + +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.update_item( - collection_id="collection_id", - item_id="item_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", +client.webhooks.create( + site_id_="580e63e98c9a982ac9b8b741", + id="582266e0cd48de0f0e3c6d8b", + trigger_type="form_submission", + url="https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", + workspace_id="4f4e46fd476ea8c507000001", + site_id="562ac0395358780a1f5e6fbd", + last_triggered=datetime.datetime.fromisoformat( + "2023-02-08 23:59:28+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2022-11-08 23:59:28+00:00", ), ) @@ -2012,15 +3304,7 @@ client.collections.items.update_item(
-**collection_id:** `str` — Unique identifier for a Collection - -
-
- -
-
- -**item_id:** `str` — Unique identifier for an Item +**site_id_:** `str` — Unique identifier for a Site
@@ -2028,7 +3312,7 @@ client.collections.items.update_item(
-**id:** `str` — Unique identifier for the Item +**id:** `typing.Optional[str]` — Unique identifier for the Webhook registration
@@ -2036,7 +3320,7 @@ client.collections.items.update_item(
-**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item +**trigger_type:** `typing.Optional[TriggerType]`
@@ -2044,7 +3328,7 @@ client.collections.items.update_item(
-**last_published:** `typing.Optional[str]` — The date the item was last published +**url:** `typing.Optional[str]` — URL to send the Webhook payload to
@@ -2052,7 +3336,7 @@ client.collections.items.update_item(
-**last_updated:** `typing.Optional[str]` — The date the item was last updated +**workspace_id:** `typing.Optional[str]` — Unique identifier for the Workspace the Webhook is registered in
@@ -2060,7 +3344,7 @@ client.collections.items.update_item(
-**created_on:** `typing.Optional[str]` — The date the item was created +**site_id:** `typing.Optional[str]` — Unique identifier for the Site the Webhook is registered in
@@ -2068,7 +3352,7 @@ client.collections.items.update_item(
-**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived +**filter:** `typing.Optional[WebhookFilter]` — Only supported for the `form_submission` trigger type. Filter for the form you want Webhooks to be sent for.
@@ -2076,7 +3360,7 @@ client.collections.items.update_item(
-**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft +**last_triggered:** `typing.Optional[dt.datetime]` — Date the Webhook instance was last triggered
@@ -2084,7 +3368,7 @@ client.collections.items.update_item(
-**field_data:** `typing.Optional[CollectionItemFieldData]` +**created_on:** `typing.Optional[dt.datetime]` — Date the Webhook registration was created
@@ -2104,7 +3388,7 @@ client.collections.items.update_item(
-
client.collections.items.get_item_live(...) +
client.webhooks.get(...)
@@ -2116,7 +3400,9 @@ client.collections.items.update_item(
-Get details of a selected Collection live Item.

Required scope | `CMS:read` +Get a specific Webhook instance + +Required scope: `sites:read`
@@ -2131,14 +3417,13 @@ Get details of a selected Collection live Item.

Required scope | `CMS
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.get_item_live( - collection_id="collection_id", - item_id="item_id", +client.webhooks.get( + webhook_id="580e64008c9a982ac9b8b754", ) ``` @@ -2155,7 +3440,7 @@ client.collections.items.get_item_live(
-**collection_id:** `str` — Unique identifier for a Collection +**webhook_id:** `str` — Unique identifier for a Webhook
@@ -2163,15 +3448,71 @@ client.collections.items.get_item_live(
-**item_id:** `str` — Unique identifier for an Item +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+ + + + +
+
client.webhooks.delete(...)
-**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. +#### 📝 Description + +
+
+ +
+
+ +Remove a Webhook + +Required scope: `sites:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.webhooks.delete( + webhook_id="580e64008c9a982ac9b8b754", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**webhook_id:** `str` — Unique identifier for a Webhook
@@ -2191,7 +3532,8 @@ client.collections.items.get_item_live(
-
client.collections.items.delete_item_live(...) +## Forms +
client.forms.list(...)
@@ -2203,7 +3545,9 @@ client.collections.items.get_item_live(
-Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` +List forms for a given site. + +Required scope | `forms:read`
@@ -2218,14 +3562,13 @@ Remove a live item from the site. Removing a published item will unpublish the i
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.delete_item_live( - collection_id="collection_id", - item_id="item_id", +client.forms.list( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2242,7 +3585,7 @@ client.collections.items.delete_item_live(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -2250,7 +3593,7 @@ client.collections.items.delete_item_live(
-**item_id:** `str` — Unique identifier for an Item +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -2258,7 +3601,7 @@ client.collections.items.delete_item_live(
-**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -2278,7 +3621,7 @@ client.collections.items.delete_item_live(
-
client.collections.items.update_item_live(...) +
client.forms.get(...)
@@ -2290,7 +3633,9 @@ client.collections.items.delete_item_live(
-Update a selected live Item in a Collection. The updates for this Item will be published to the live site.

Required scope | `CMS:write` +Get information about a given form. + +Required scope | `forms:read`
@@ -2305,26 +3650,13 @@ Update a selected live Item in a Collection. The updates for this Item will be p
```python -from webflow import CollectionItemFieldData -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.update_item_live( - collection_id="collection_id", - item_id="item_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), +client.forms.get( + form_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2341,7 +3673,7 @@ client.collections.items.update_item_live(
-**collection_id:** `str` — Unique identifier for a Collection +**form_id:** `str` — Unique identifier for a Form
@@ -2349,55 +3681,71 @@ client.collections.items.update_item_live(
-**item_id:** `str` — Unique identifier for an Item +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
-
-
-**id:** `str` — Unique identifier for the Item -
+
+
client.forms.list_submissions(...)
-**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item - -
-
+#### 📝 Description
-**last_published:** `typing.Optional[str]` — The date the item was last published - +
+
+ +List form submissions for a given form + +Required scope | `forms:read` +
+
+#### 🔌 Usage +
-**last_updated:** `typing.Optional[str]` — The date the item was last updated - +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.forms.list_submissions( + form_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+#### ⚙️ Parameters +
-**created_on:** `typing.Optional[str]` — The date the item was created - -
-
-
-**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived +**form_id:** `str` — Unique identifier for a Form
@@ -2405,7 +3753,7 @@ client.collections.items.update_item_live(
-**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -2413,7 +3761,7 @@ client.collections.items.update_item_live(
-**field_data:** `typing.Optional[CollectionItemFieldData]` +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -2433,7 +3781,7 @@ client.collections.items.update_item_live(
-
client.collections.items.publish_item(...) +
client.forms.get_submission(...)
@@ -2445,7 +3793,9 @@ client.collections.items.update_item_live(
-Publish an item or multiple items.

Required scope | `cms:write` +Get information about a given form submissio. + +Required scope | `forms:read`
@@ -2460,14 +3810,13 @@ Publish an item or multiple items.

Required scope | `cms:write`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.publish_item( - collection_id="collection_id", - item_ids=["itemIds"], +client.forms.get_submission( + form_submission_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2484,15 +3833,7 @@ client.collections.items.publish_item(
-**collection_id:** `str` — Unique identifier for a Collection - -
-
- -
-
- -**item_ids:** `typing.Sequence[str]` +**form_submission_id:** `str` — Unique identifier for a Form Submission
@@ -2512,8 +3853,7 @@ client.collections.items.publish_item(
-## Pages -
client.pages.list(...) +
client.forms.update_submission(...)
@@ -2525,7 +3865,9 @@ client.collections.items.publish_item(
-List of all pages for a site

Required scope | `pages:read` +Update hidden fields on a form submission + +Required scope | `forms:write`
@@ -2540,13 +3882,13 @@ List of all pages for a site

Required scope | `pages:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.list( - site_id="site_id", +client.forms.update_submission( + form_submission_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2563,23 +3905,7 @@ client.pages.list(
-**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- -**locale:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. - -
-
- -
-
- -**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**form_submission_id:** `str` — Unique identifier for a Form Submission
@@ -2587,7 +3913,7 @@ client.pages.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set
@@ -2607,7 +3933,8 @@ client.pages.list(
-
client.pages.get_metadata(...) +## Users +
client.users.list(...)
@@ -2619,7 +3946,9 @@ client.pages.list(
-Get metadata information for a single page

Required scope | `pages:read` +Get a list of users for a site + +Required scope | `users:read`
@@ -2634,13 +3963,13 @@ Get metadata information for a single page

Required scope | `pages:re
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.get_metadata( - page_id="page_id", +client.users.list( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2657,7 +3986,23 @@ client.pages.get_metadata(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -2665,7 +4010,13 @@ client.pages.get_metadata(
-**locale:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**sort:** `typing.Optional[UsersListRequestSort]` + +Sort string to use when ordering users + +Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). + +Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
@@ -2685,7 +4036,7 @@ client.pages.get_metadata(
-
client.pages.update_page_settings(...) +
client.users.get(...)
@@ -2697,7 +4048,9 @@ client.pages.get_metadata(
-Update Page-level metadata, including SEO and Open Graph fields.

Required scope | `pages:write` +Get a User by ID + +Required scope | `users:read`
@@ -2712,41 +4065,14 @@ Update Page-level metadata, including SEO and Open Graph fields.

Requ
```python -import datetime - -from webflow import PageOpenGraph, PageSeo -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.update_page_settings( - page_id="page_id", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", - title="Guide to the Galaxy", - slug="guide-to-the-galaxy", - parent_id="6419db964a9c435aa3af6251", - collection_id="6390c49774a71f12831a08e3", - created_on=datetime.datetime.fromisoformat( - "2024-03-11 10:42:00+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2024-03-11 10:42:42+00:00", - ), - archived=False, - draft=False, - can_branch=True, - seo=PageSeo( - title="The Ultimate Hitchhiker's Guide to the Galaxy", - description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", - ), - open_graph=PageOpenGraph( - title="Explore the Cosmos with The Ultimate Guide", - title_copied=False, - description="Dive deep into the mysteries of the universe with your guide to everything galactic.", - description_copied=False, - ), +client.users.get( + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", ) ``` @@ -2763,7 +4089,7 @@ client.pages.update_page_settings(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site
@@ -2771,7 +4097,7 @@ client.pages.update_page_settings(
-**locale:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**user_id:** `str` — Unique identifier for a User
@@ -2779,103 +4105,72 @@ client.pages.update_page_settings(
-**id:** `typing.Optional[str]` — Unique identifier for the Page +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
- -
-
- -**site_id:** `typing.Optional[str]` — Unique identifier for the Site -
-
-
-**title:** `typing.Optional[str]` — Title of the Page -
+
+
client.users.delete(...)
-**slug:** `typing.Optional[str]` — slug of the Page (derived from title) - -
-
+#### 📝 Description
-**parent_id:** `typing.Optional[str]` — Identifier of the parent folder - -
-
-
-**collection_id:** `typing.Optional[str]` — Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. - +Delete a User by ID + +Required scope | `users:write`
- -
-
- -**created_on:** `typing.Optional[dt.datetime]` — The date the Page was created -
+#### 🔌 Usage +
-**last_updated:** `typing.Optional[dt.datetime]` — The date the Page was most recently updated - -
-
-
-**archived:** `typing.Optional[bool]` — Whether the Page has been archived - -
-
+```python +from webflow import Webflow -
-
+client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.users.delete( + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", +) -**draft:** `typing.Optional[bool]` — Whether the Page is a draft - +```
- -
-
- -**can_branch:** `typing.Optional[bool]` — Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) -
+#### ⚙️ Parameters +
-**is_members_only:** `typing.Optional[bool]` — Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) - -
-
-
-**seo:** `typing.Optional[PageSeo]` — SEO-related fields for the Page +**site_id:** `str` — Unique identifier for a Site
@@ -2883,7 +4178,7 @@ client.pages.update_page_settings(
-**open_graph:** `typing.Optional[PageOpenGraph]` — Open Graph fields for the Page +**user_id:** `str` — Unique identifier for a User
@@ -2903,7 +4198,7 @@ client.pages.update_page_settings(
-
client.pages.get_content(...) +
client.users.update(...)
@@ -2915,7 +4210,12 @@ client.pages.update_page_settings(
-Get static content from a static page.
If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale

Required scope | `pages:read` +Update a User by ID + + Required scope | `users:write` + +The email and password +fields cannot be updated using this endpoint
@@ -2930,13 +4230,21 @@ Get static content from a static page.
If you do not provide a Locale ID i
```python -from webflow.client import Webflow +from webflow import Webflow +from webflow.resources.users import UsersUpdateRequestData client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.get_content( - page_id="page_id", +client.users.update( + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", + data=UsersUpdateRequestData( + name="Some One", + accept_privacy=False, + accept_communications=False, + ), + access_groups=["webflowers", "platinum", "free-tier"], ) ``` @@ -2953,7 +4261,7 @@ client.pages.get_content(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site
@@ -2961,7 +4269,7 @@ client.pages.get_content(
-**locale:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**user_id:** `str` — Unique identifier for a User
@@ -2969,7 +4277,7 @@ client.pages.get_content(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**data:** `typing.Optional[UsersUpdateRequestData]`
@@ -2977,7 +4285,8 @@ client.pages.get_content(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**access_groups:** `typing.Optional[typing.Sequence[str]]` — An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. +
@@ -2997,7 +4306,7 @@ client.pages.get_content(
-
client.pages.update_static_content(...) +
client.users.invite(...)
@@ -3009,7 +4318,11 @@ client.pages.get_content(
-Update static content on a static page. This endpoint supports sending 1000 nodes per request.

Required scope | `pages:write` +Create and invite a user with an email address. + +The user will be sent and invite via email, which they will need to accept in order to join paid any paid access group. + +Required scope | `users:write`
@@ -3024,29 +4337,15 @@ Update static content on a static page. This endpoint supports sending 1000 node
```python -from webflow import DomWriteNodesItem -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.update_static_content( - page_id="page_id", - locale="locale", - nodes=[ - DomWriteNodesItem( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", - text="

The Hitchhiker's Guide to the Galaxy

", - ), - DomWriteNodesItem( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", - text="

Don't Panic!

Always know where your towel is.

", - ), - DomWriteNodesItem( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", - text="Marvin, the Paranoid Android", - ), - ], +client.users.invite( + site_id="580e63e98c9a982ac9b8b741", + email="some.one@home.com", + access_groups=["webflowers"], ) ``` @@ -3063,7 +4362,7 @@ client.pages.update_static_content(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site
@@ -3071,7 +4370,7 @@ client.pages.update_static_content(
-**locale:** `str` — The locale identifier. +**email:** `str` — Email address of user to send invite to
@@ -3079,7 +4378,8 @@ client.pages.update_static_content(
-**nodes:** `typing.Sequence[DomWriteNodesItem]` +**access_groups:** `typing.Optional[typing.Sequence[str]]` — An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. +
@@ -3099,8 +4399,8 @@ client.pages.update_static_content(
-## Pages Scripts -
client.pages.scripts.get_custom_code(...) +## AccessGroups +
client.access_groups.list(...)
@@ -3112,7 +4412,9 @@ client.pages.update_static_content(
-Get all registered scripts that have been applied to a specific Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` +Get a list of access groups for a site + +Required scope | `users:read`
@@ -3127,13 +4429,13 @@ Get all registered scripts that have been applied to a specific Page.

```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.scripts.get_custom_code( - page_id="page_id", +client.access_groups.list( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -3150,7 +4452,34 @@ client.pages.scripts.get_custom_code(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**sort:** `typing.Optional[AccessGroupsListRequestSort]` + +Sort string to use when ordering access groups +Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
@@ -3170,7 +4499,8 @@ client.pages.scripts.get_custom_code(
-
client.pages.scripts.upsert_custom_code(...) +## Products +
client.products.list(...)
@@ -3182,7 +4512,12 @@ client.pages.scripts.get_custom_code(
-Add a registered script to a Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` +Retrieve all products for a site. + +Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product +will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. + +Required scope | `ecommerce:read`
@@ -3197,27 +4532,13 @@ Add a registered script to a Page.

In order to use the Custom Code AP
```python -from webflow import ScriptApply, ScriptApplyLocation -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.scripts.upsert_custom_code( - page_id="page_id", - scripts=[ - ScriptApply( - id="cms_slider", - location=ScriptApplyLocation.HEADER, - version="1.0.0", - attributes={"my-attribute": "some-value"}, - ), - ScriptApply( - id="alert", - location=ScriptApplyLocation.HEADER, - version="0.0.1", - ), - ], +client.products.list( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -3234,15 +4555,7 @@ client.pages.scripts.upsert_custom_code(
-**page_id:** `str` — Unique identifier for a Page - -
-
- -
-
- -**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page +**site_id:** `str` — Unique identifier for a Site
@@ -3250,7 +4563,7 @@ client.pages.scripts.upsert_custom_code(
-**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -3258,7 +4571,7 @@ client.pages.scripts.upsert_custom_code(
-**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -3278,7 +4591,7 @@ client.pages.scripts.upsert_custom_code(
-
client.pages.scripts.delete_custom_code(...) +
client.products.create(...)
@@ -3290,7 +4603,20 @@ client.pages.scripts.upsert_custom_code(
-Delete the custom code block that an app has created for a page

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` +Create a new product and SKU. + +When you create a product, you will always create a SKU, since a Product Item must have, at minimum, a single SKU. + +To create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large: + - Create parameters in `sku-properties`, also known as [product options and variants.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). + - A single `sku-property` would be `color`. Within the `color` property, list the various colors of T-shirts as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. + - Once, you've created a Product and its `sku-properties` with `enum` values, Webflow will create a **default SKU**, which will automatically be a combination of the first `sku-properties` you've created. + - In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. + - After you've created your product, you can create additional SKUs using the [Create SKU endpoint.](/data/reference/ecommerce/products/create-sku) + +Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + +Required scope | `ecommerce:write`
@@ -3305,13 +4631,13 @@ Delete the custom code block that an app has created for a page

In or
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.scripts.delete_custom_code( - page_id="page_id", +client.products.create( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -3328,7 +4654,31 @@ client.pages.scripts.delete_custom_code(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**publish_status:** `typing.Optional[PublishStatus]` + +
+
+ +
+
+ +**product:** `typing.Optional[Product]` + +
+
+ +
+
+ +**sku:** `typing.Optional[Sku]`
@@ -3348,8 +4698,7 @@ client.pages.scripts.delete_custom_code(
-## Sites Scripts -
client.sites.scripts.get_custom_code(...) +
client.products.get(...)
@@ -3361,7 +4710,10 @@ client.pages.scripts.delete_custom_code(
-Get all registered scripts that have been applied to a specific Site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` +Retrieve a single product by its ID. All of its SKUs will also be +retrieved. + +Required scope | `ecommerce:read`
@@ -3376,13 +4728,14 @@ Get all registered scripts that have been applied to a specific Site. ```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.scripts.get_custom_code( - site_id="site_id", +client.products.get( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -3407,6 +4760,14 @@ client.sites.scripts.get_custom_code(
+**product_id:** `str` — Unique identifier for a Product + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -3419,7 +4780,7 @@ client.sites.scripts.get_custom_code(
-
client.sites.scripts.upsert_custom_code(...) +
client.products.update(...)
@@ -3431,7 +4792,11 @@ client.sites.scripts.get_custom_code(
-Add a registered script to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` +Update an existing Product. + +Updating an existing Product will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + +Required scope | `ecommerce:write`
@@ -3446,27 +4811,14 @@ Add a registered script to a Site.

In order to use the Custom Code AP
```python -from webflow import ScriptApply, ScriptApplyLocation -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.scripts.upsert_custom_code( - site_id="site_id", - scripts=[ - ScriptApply( - id="cms_slider", - location=ScriptApplyLocation.HEADER, - version="1.0.0", - attributes={"my-attribute": "some-value"}, - ), - ScriptApply( - id="alert", - location=ScriptApplyLocation.HEADER, - version="0.0.1", - ), - ], +client.products.update( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -3491,7 +4843,7 @@ client.sites.scripts.upsert_custom_code(
-**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page +**product_id:** `str` — Unique identifier for a Product
@@ -3499,7 +4851,7 @@ client.sites.scripts.upsert_custom_code(
-**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated +**publish_status:** `typing.Optional[PublishStatus]`
@@ -3507,7 +4859,15 @@ client.sites.scripts.upsert_custom_code(
-**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created +**product:** `typing.Optional[Product]` + +
+
+ +
+
+ +**sku:** `typing.Optional[Sku]`
@@ -3527,7 +4887,7 @@ client.sites.scripts.upsert_custom_code(
-
client.sites.scripts.delete_custom_code(...) +
client.products.create_sku(...)
@@ -3539,7 +4899,11 @@ client.sites.scripts.upsert_custom_code(
-Delete the custom code block that an app created for a Site

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` +Create additional SKUs to manage every [option and variant of your Product.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants) + +Creating SKUs through the API will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + +Required scope | `ecommerce:write`
@@ -3554,13 +4918,15 @@ Delete the custom code block that an app created for a Site

```python -from webflow.client import Webflow +from webflow import Sku, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.scripts.delete_custom_code( - site_id="site_id", +client.products.create_sku( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + skus=[Sku()], ) ``` @@ -3585,6 +4951,30 @@ client.sites.scripts.delete_custom_code(
+**product_id:** `str` — Unique identifier for a Product + +
+
+ +
+
+ +**skus:** `typing.Sequence[Sku]` — An array of the SKU data your are adding + +
+
+ +
+
+ +**publish_status:** `typing.Optional[PublishStatus]` + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -3597,7 +4987,7 @@ client.sites.scripts.delete_custom_code(
-
client.sites.scripts.list_custom_code_blocks(...) +
client.products.update_sku(...)
@@ -3609,7 +4999,11 @@ client.sites.scripts.delete_custom_code(
-Get all instances of Custom Code applied to a Site or Pages.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` +Update a specified SKU. + +Updating an existing SKU will set the Product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + +Required scope | `ecommerce:write`
@@ -3624,13 +5018,16 @@ Get all instances of Custom Code applied to a Site or Pages.
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**product_id:** `str` — Unique identifier for a Product
@@ -3663,7 +5060,23 @@ client.sites.scripts.list_custom_code_blocks(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**sku_id:** `str` — Unique identifier for a SKU + +
+
+ +
+
+ +**sku:** `Sku` + +
+
+ +
+
+ +**publish_status:** `typing.Optional[PublishStatus]`
@@ -3683,8 +5096,8 @@ client.sites.scripts.list_custom_code_blocks(
-## Scripts -
client.scripts.list(...) +## Orders +
client.orders.list(...)
@@ -3696,7 +5109,9 @@ client.sites.scripts.list_custom_code_blocks(
-List of scripts registered to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` +List all orders created for a given site. + +Required scope | `ecommerce:read`
@@ -3711,13 +5126,13 @@ List of scripts registered to a Site.

In order to use the Custom Code
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.scripts.list( - site_id="site_id", +client.orders.list( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -3742,6 +5157,30 @@ client.scripts.list(
+**status:** `typing.Optional[OrdersListRequestStatus]` — Filter the orders by status + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -3754,7 +5193,7 @@ client.scripts.list(
-
client.scripts.register_hosted(...) +
client.orders.get(...)
@@ -3766,7 +5205,10 @@ client.scripts.list(
-Add a script to a Site's Custom Code registry.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.


Required scope | `custom_code:write` +Retrieve a single product by its ID. All of its SKUs will also be +retrieved. + +Required scope | `ecommerce:read`
@@ -3781,17 +5223,14 @@ Add a script to a Site's Custom Code registry.

In order to use the Cu
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.scripts.register_hosted( - site_id="site_id", - hosted_location="hostedLocation", - integrity_hash="integrityHash", - version="version", - display_name="displayName", +client.orders.get( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) ``` @@ -3808,39 +5247,7 @@ client.scripts.register_hosted(
-**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- -**hosted_location:** `str` — URI for an externally hosted script location - -
-
- -
-
- -**integrity_hash:** `str` — Sub-Resource Integrity Hash - -
-
- -
-
- -**version:** `str` — A Semantic Version (SemVer) string, denoting the version of the script - -
-
- -
-
- -**display_name:** `str` — User-facing name for the script. Must be between 1 and 50 alphanumeric characters +**site_id:** `str` — Unique identifier for a Site
@@ -3848,7 +5255,7 @@ client.scripts.register_hosted(
-**can_copy:** `typing.Optional[bool]` — Define whether the script can be copied on site duplication and transfer +**order_id:** `str` — Unique identifier for an Order
@@ -3868,7 +5275,7 @@ client.scripts.register_hosted(
-
client.scripts.register_inline(...) +
client.orders.update(...)
@@ -3880,7 +5287,11 @@ client.scripts.register_hosted(
-Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` +This API lets you update the fields, `comment`, `shippingProvider`, +and/or `shippingTracking` for a given order. All three fields can be +updated simultaneously or independently. + +Required scope | `ecommerce:write`
@@ -3895,16 +5306,14 @@ Add a script to a Site's Custom Code registry. Inline scripts can be between 1 a
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.scripts.register_inline( - site_id="site_id", - source_code="alert('hello world');", - version="0.0.1", - display_name="Alert", +client.orders.update( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) ``` @@ -3929,7 +5338,7 @@ client.scripts.register_inline(
-**source_code:** `str` — The code to be added to the site (to be hosted by Webflow). +**order_id:** `str` — Unique identifier for an Order
@@ -3937,7 +5346,7 @@ client.scripts.register_inline(
-**version:** `str` — A Semantic Version (SemVer) string, denoting the version of the script +**comment:** `typing.Optional[str]` — Arbitrary data for your records
@@ -3945,7 +5354,7 @@ client.scripts.register_inline(
-**display_name:** `str` — User-facing name for the script. Must be between 1 and 50 alphanumeric characters +**shipping_provider:** `typing.Optional[str]` — Company or method used to ship order
@@ -3953,7 +5362,7 @@ client.scripts.register_inline(
-**integrity_hash:** `typing.Optional[str]` — Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) +**shipping_tracking:** `typing.Optional[str]` — Tracking number for order shipment
@@ -3961,7 +5370,7 @@ client.scripts.register_inline(
-**can_copy:** `typing.Optional[bool]` — Define whether the script can be copied on site duplication and transfer +**shipping_tracking_url:** `typing.Optional[str]` — URL to track order shipment
@@ -3981,8 +5390,7 @@ client.scripts.register_inline(
-## Assets -
client.assets.list(...) +
client.orders.update_fulfill(...)
@@ -3994,7 +5402,9 @@ client.scripts.register_inline(
-List assets for a given site

Required scope | `assets:read` +Updates an order's status to fulfilled + +Required scope | `ecommerce:write`
@@ -4009,13 +5419,14 @@ List assets for a given site

Required scope | `assets:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.assets.list( - site_id="site_id", +client.orders.update_fulfill( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) ``` @@ -4040,6 +5451,22 @@ client.assets.list(
+**order_id:** `str` — Unique identifier for an Order + +
+
+ +
+
+ +**send_order_fulfilled_email:** `typing.Optional[bool]` — Whether or not the Order Fulfilled email should be sent + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -4052,7 +5479,7 @@ client.assets.list(
-
client.assets.create(...) +
client.orders.update_unfulfill(...)
@@ -4064,7 +5491,9 @@ client.assets.list(
-Create a new asset entry.

This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) request to the `uploadUrl` with the `uploadDetails` object as your header information in the request.

Required scope | `assets:write` +Updates an order's status to unfulfilled + +Required scope | `ecommerce:write`
@@ -4079,15 +5508,14 @@ Create a new asset entry.

This endpoint generates a response with the
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.assets.create( - site_id="site_id", - file_name="file.png", - file_hash="3c7d87c9575702bc3b1e991f4d3c638e", +client.orders.update_unfulfill( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) ``` @@ -4112,23 +5540,7 @@ client.assets.create(
-**file_name:** `str` — file name including file extension - -
-
- -
-
- -**file_hash:** `str` — MD5 hash of the file - -
-
- -
-
- -**parent_folder:** `typing.Optional[str]` — id of the Asset folder (optional) +**order_id:** `str` — Unique identifier for an Order
@@ -4148,7 +5560,7 @@ client.assets.create(
-
client.assets.get(...) +
client.orders.refund(...)
@@ -4160,7 +5572,10 @@ client.assets.create(
-Get an Asset

Required scope | `assets:read` +This API will reverse a Stripe charge and refund an order back to a +customer. It will also set the order's status to `refunded`. + +Required scope | `ecommerce:write`
@@ -4175,13 +5590,14 @@ Get an Asset

Required scope | `assets:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.assets.get( - asset_id="asset_id", +client.orders.refund( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) ``` @@ -4198,7 +5614,23 @@ client.assets.get(
-**asset_id:** `str` — Unique identifier for an Asset on a site +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**order_id:** `str` — Unique identifier for an Order + +
+
+ +
+
+ +**reason:** `typing.Optional[OrdersRefundRequestReason]` — The reason for the refund
@@ -4218,7 +5650,8 @@ client.assets.get(
-
client.assets.delete(...) +## Inventory +
client.inventory.list(...)
@@ -4230,7 +5663,9 @@ client.assets.get(
-Delete an Asset +List the current inventory levels for a particular SKU item. + +Required scope | `ecommerce:read`
@@ -4245,13 +5680,14 @@ Delete an Asset
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.assets.delete( - asset_id="asset_id", +client.inventory.list( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) ``` @@ -4268,7 +5704,15 @@ client.assets.delete(
-**asset_id:** `str` — Unique identifier for an Asset on a site +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_id:** `str` — Unique identifier for an Item
@@ -4288,7 +5732,7 @@ client.assets.delete(
-
client.assets.update(...) +
client.inventory.update(...)
@@ -4300,7 +5744,13 @@ client.assets.delete(
-Update an Asset

Required scope | `assets:write` +Updates the current inventory levels for a particular SKU item. + +Updates may be given in one or two methods, absolutely or incrementally. +- Absolute updates are done by setting `quantity` directly. +- Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. + +Required scope | `ecommerce:write`
@@ -4315,14 +5765,15 @@ Update an Asset

Required scope | `assets:write`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.assets.update( - asset_id="asset_id", - display_name="bulldoze.png", +client.inventory.update( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + inventory_type="infinite", ) ``` @@ -4339,7 +5790,31 @@ client.assets.update(
-**asset_id:** `str` — Unique identifier for an Asset on a site +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**inventory_type:** `InventoryUpdateRequestInventoryType` — infinite or finite + +
+
+ +
+
+ +**update_quantity:** `typing.Optional[float]` — Adds this quantity to currently store quantity. Can be negative.
@@ -4347,7 +5822,7 @@ client.assets.update(
-**display_name:** `str` — file name including file extension +**quantity:** `typing.Optional[float]` — Immediately sets quantity to this value.
@@ -4367,7 +5842,8 @@ client.assets.update(
-
client.assets.list_folders(...) +## Ecommerce +
client.ecommerce.get_settings(...)
@@ -4379,7 +5855,9 @@ client.assets.update(
-List Asset Folders within a given site

Required scope | `assets:read` +Retrieve ecommerce settings for a site. + +Required scope | `ecommerce:read`
@@ -4394,13 +5872,13 @@ List Asset Folders within a given site

Required scope | `assets:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.assets.list_folders( - site_id="site_id", +client.ecommerce.get_settings( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -4437,7 +5915,8 @@ client.assets.list_folders(
-
client.assets.create_folder(...) +## Collections Fields +
client.collections.fields.create(...)
@@ -4449,7 +5928,16 @@ client.assets.list_folders(
-Create an Asset Folder within a given site

Required scope | `assets:write` +Create a custom field in a collection. + +Slugs must be all lowercase letters without spaces. +If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will +convert the slug to lowercase and replace spaces with "-." + +Only some field types can be created through the API. +This endpoint does not currently support bulk creation. + +Required scope | `cms:write`
@@ -4464,14 +5952,17 @@ Create an Asset Folder within a given site

Required scope | `assets:wri
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.assets.create_folder( - site_id="site_id", - display_name="my asset folder", +client.collections.fields.create( + collection_id="580e63fc8c9a982ac9b8b745", + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", ) ``` @@ -4488,7 +5979,7 @@ client.assets.create_folder(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -4496,7 +5987,7 @@ client.assets.create_folder(
-**display_name:** `str` — A human readable name for the Asset Folder +**type:** `FieldCreateType` — Choose these appropriate field type for your collection data
@@ -4504,7 +5995,23 @@ client.assets.create_folder(
-**parent_folder:** `typing.Optional[str]` — An (optional) pointer to a parent Asset Folder (or null for root) +**display_name:** `str` — The name of a field + +
+
+ +
+
+ +**is_required:** `typing.Optional[bool]` — define whether a field is required in a collection + +
+
+ +
+
+ +**help_text:** `typing.Optional[str]` — Additional text to help anyone filling out this field
@@ -4524,7 +6031,7 @@ client.assets.create_folder(
-
client.assets.get_folder(...) +
client.collections.fields.delete(...)
@@ -4536,7 +6043,9 @@ client.assets.create_folder(
-Get details about a specific Asset Folder

Required scope | `assets:read` +Delete a custom field in a collection. This endpoint does not currently support bulk deletion. + +Required scope | `cms:write`
@@ -4551,13 +6060,14 @@ Get details about a specific Asset Folder

Required scope | `assets:read
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.assets.get_folder( - asset_folder_id="asset_folder_id", +client.collections.fields.delete( + collection_id="580e63fc8c9a982ac9b8b745", + field_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -4574,7 +6084,15 @@ client.assets.get_folder(
-**asset_folder_id:** `str` — Unique identifier for an Asset Folder +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**field_id:** `str` — Unique identifier for a Field in a collection
@@ -4594,8 +6112,7 @@ client.assets.get_folder(
-## Webhooks -
client.webhooks.list(...) +
client.collections.fields.update(...)
@@ -4607,7 +6124,9 @@ client.assets.get_folder(
-List all App-created Webhooks registered for a given site

Required scope | `sites:read` +Update a custom field in a collection. + +Required scope | `cms:write`
@@ -4622,13 +6141,17 @@ List all App-created Webhooks registered for a given site

Required sc
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.webhooks.list( - site_id="site_id", +client.collections.fields.update( + collection_id="580e63fc8c9a982ac9b8b745", + field_id="580e63fc8c9a982ac9b8b745", + is_required=False, + display_name="Post Body", + help_text="Add the body of your post here", ) ``` @@ -4645,7 +6168,39 @@ client.webhooks.list(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**field_id:** `str` — Unique identifier for a Field in a collection + +
+
+ +
+
+ +**is_required:** `typing.Optional[bool]` — Define whether a field is required in a collection + +
+
+ +
+
+ +**display_name:** `typing.Optional[str]` — The name of a field + +
+
+ +
+
+ +**help_text:** `typing.Optional[str]` — Additional text to help anyone filling out this field
@@ -4665,7 +6220,8 @@ client.webhooks.list(
-
client.webhooks.create(...) +## Collections Items +
client.collections.items.list_items(...)
@@ -4677,7 +6233,9 @@ client.webhooks.list(
-Create a new Webhook, to be notified when Webflow resources change. Limit of 75 registrations per `triggerType`, per site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `sites:write` +List of all Items within a Collection. + +Required scope | `CMS:read`
@@ -4692,16 +6250,13 @@ Create a new Webhook, to be notified when Webflow resources change. Limit of 75
```python -from webflow import TriggerType -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.webhooks.create( - site_id="site_id", - trigger_type=TriggerType.FORM_SUBMISSION, - url="https://api.mydomain.com/webhook", +client.collections.items.list_items( + collection_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -4718,7 +6273,23 @@ client.webhooks.create(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -4726,7 +6297,7 @@ client.webhooks.create(
-**trigger_type:** `TriggerType` +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100)
@@ -4734,8 +6305,15 @@ client.webhooks.create(
-**url:** `str` — The server URI that Webflow will call when your Webhook is triggered +**name:** `typing.Optional[str]` — The name of the item(s) + +
+
+ +
+
+**slug:** `typing.Optional[str]` — The slug of the item
@@ -4743,11 +6321,15 @@ client.webhooks.create(
-**filter:** `typing.Optional[typing.Dict[str, typing.Any]]` +**sort_by:** `typing.Optional[ItemsListItemsRequestSortBy]` — Sort results by the provided value + +
+
-Filter for selecting which events you want Webhooks to be triggered for. -** Only available for `form_submission` trigger types. ** +
+
+**sort_order:** `typing.Optional[ItemsListItemsRequestSortOrder]` — Sorts the results by asc or desc
@@ -4767,7 +6349,7 @@ Filter for selecting which events you want Webhooks to be triggered for.
-
client.webhooks.get(...) +
client.collections.items.create_item(...)
@@ -4779,7 +6361,12 @@ Filter for selecting which events you want Webhooks to be triggered for.
-Get a specific Webhook instance +Create Item(s) in a Collection. + + +To create items across multiple locales, please use [this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + +Required scope | `CMS:write`
@@ -4794,13 +6381,38 @@ Get a specific Webhook instance
```python -from webflow.client import Webflow +from webflow import ( + CollectionItemPostSingle, + CollectionItemPostSingleFieldData, + Webflow, +) +from webflow.resources.collections.resources.items import MultipleItems client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.webhooks.get( - webhook_id="webhook_id", +client.collections.items.create_item( + collection_id="580e63fc8c9a982ac9b8b745", + request=MultipleItems( + items=[ + CollectionItemPostSingle( + is_archived=False, + is_draft=False, + field_data=CollectionItemPostSingleFieldData( + name="Senior Data Analyst", + slug="senior-data-analyst", + ), + ), + CollectionItemPostSingle( + is_archived=False, + is_draft=False, + field_data=CollectionItemPostSingleFieldData( + name="Product Manager", + slug="product-manager", + ), + ), + ], + ), ) ``` @@ -4817,7 +6429,15 @@ client.webhooks.get(
-**webhook_id:** `str` — Unique identifier for a Webhook +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**request:** `ItemsCreateItemRequest`
@@ -4837,7 +6457,7 @@ client.webhooks.get(
-
client.webhooks.delete(...) +
client.collections.items.delete_items(...)
@@ -4849,7 +6469,11 @@ client.webhooks.get(
-Remove a Webhook +Delete Items from a Collection. + +**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be deleted only in the primary locale. + +Required scope | `CMS:write`
@@ -4864,13 +6488,13 @@ Remove a Webhook
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.webhooks.delete( - webhook_id="webhook_id", +client.collections.items.delete_items( + collection_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -4887,7 +6511,15 @@ client.webhooks.delete(
-**webhook_id:** `str` — Unique identifier for a Webhook +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**items:** `typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]]`
@@ -4907,8 +6539,7 @@ client.webhooks.delete(
-## Forms -
client.forms.list(...) +
client.collections.items.update_items(...)
@@ -4920,7 +6551,11 @@ client.webhooks.delete(
-List forms for a given site

Required scope | `forms:read` +Update a single item or multiple items (up to 100) in a Collection. + +**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + +Required scope | `CMS:write`
@@ -4935,13 +6570,51 @@ List forms for a given site

Required scope | `forms:read`
```python -from webflow.client import Webflow +from webflow import ( + CollectionItemWithIdInput, + CollectionItemWithIdInputFieldData, + Webflow, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.forms.list( - site_id="site_id", +client.collections.items.update_items( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Ne Paniquez Pas", + slug="ne-paniquez-pas", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="No Entrar en Pánico", + slug="no-entrar-en-panico", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Au Revoir et Merci pour Tous les Poissons", + slug="au-revoir-et-merci", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="Hasta Luego y Gracias por Todo el Pescado", + slug="hasta-luego-y-gracias", + ), + ), + ], ) ``` @@ -4958,15 +6631,7 @@ client.forms.list(
-**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- -**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**collection_id:** `str` — Unique identifier for a Collection
@@ -4974,7 +6639,7 @@ client.forms.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**items:** `typing.Optional[typing.Sequence[CollectionItemWithIdInput]]`
@@ -4994,7 +6659,7 @@ client.forms.list(
-
client.forms.get(...) +
client.collections.items.list_items_live(...)
@@ -5006,7 +6671,9 @@ client.forms.list(
-Get information about a given form

Required scope | `forms:read` +List of all live Items within a Collection. + +Required scope | `CMS:read`
@@ -5021,13 +6688,13 @@ Get information about a given form

Required scope | `forms:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.forms.get( - form_id="form_id", +client.collections.items.list_items_live( + collection_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -5044,7 +6711,63 @@ client.forms.get(
-**form_id:** `str` — Unique identifier for a Form +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**name:** `typing.Optional[str]` — The name of the item(s) + +
+
+ +
+
+ +**slug:** `typing.Optional[str]` — The slug of the item + +
+
+ +
+
+ +**sort_by:** `typing.Optional[ItemsListItemsLiveRequestSortBy]` — Sort results by the provided value + +
+
+ +
+
+ +**sort_order:** `typing.Optional[ItemsListItemsLiveRequestSortOrder]` — Sorts the results by asc or desc
@@ -5064,7 +6787,7 @@ client.forms.get(
-
client.forms.list_submissions(...) +
client.collections.items.create_item_live(...)
@@ -5076,7 +6799,13 @@ client.forms.get(
-List form submissions for a given form

Required scope | `forms:read` +Create live Item(s) in a Collection. The Item(s) will be published to the live site. + + +To create items across multiple locales, [please use this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + + +Required scope | `CMS:write`
@@ -5091,13 +6820,34 @@ List form submissions for a given form

Required scope | `forms:read`
```python -from webflow.client import Webflow +from webflow import CollectionItem, CollectionItemFieldData, Webflow +from webflow.resources.collections.resources.items import MultipleLiveItems client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.forms.list_submissions( - form_id="form_id", +client.collections.items.create_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + request=MultipleLiveItems( + items=[ + CollectionItem( + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Senior Data Analyst", + slug="senior-data-analyst", + ), + ), + CollectionItem( + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Product Manager", + slug="product-manager", + ), + ), + ], + ), ) ``` @@ -5114,7 +6864,15 @@ client.forms.list_submissions(
-**form_id:** `str` — Unique identifier for a Form +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**request:** `ItemsCreateItemLiveRequest`
@@ -5134,7 +6892,7 @@ client.forms.list_submissions(
-
client.forms.get_submission(...) +
client.collections.items.delete_items_live(...)
@@ -5146,7 +6904,11 @@ client.forms.list_submissions(
-Get information about a given form submission

Required scope | `forms:read` +Remove an item or multiple items (up to 100 items) from the live site. Deleting published items will unpublish the items from the live site and set them to draft. + +**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be unpublished only in the primary locale. + +Required scope | `CMS:write`
@@ -5161,13 +6923,13 @@ Get information about a given form submission

Required scope | `forms:
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.forms.get_submission( - form_submission_id="form_submission_id", +client.collections.items.delete_items_live( + collection_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -5184,7 +6946,15 @@ client.forms.get_submission(
-**form_submission_id:** `str` — Unique identifier for a Form Submission +**collection_id:** `str` — Unique identifier for a Collection + +
+
+ +
+
+ +**items:** `typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]]`
@@ -5204,7 +6974,7 @@ client.forms.get_submission(
-
client.forms.update_submission(...) +
client.collections.items.update_items_live(...)
@@ -5216,7 +6986,11 @@ client.forms.get_submission(
-Update hidden fields on a form submission

Required scope | `forms:write` +Update a single live item or multiple live items (up to 100) in a Collection + +**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + +Required scope | `CMS:write`
@@ -5231,13 +7005,51 @@ Update hidden fields on a form submission

Required scope | `forms:writ
```python -from webflow.client import Webflow +from webflow import ( + CollectionItemWithIdInput, + CollectionItemWithIdInputFieldData, + Webflow, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.forms.update_submission( - form_submission_id="form_submission_id", +client.collections.items.update_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Ne Paniquez Pas", + slug="ne-paniquez-pas", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="No Entrar en Pánico", + slug="no-entrar-en-panico", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Au Revoir et Merci pour Tous les Poissons", + slug="au-revoir-et-merci", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="Hasta Luego y Gracias por Todo el Pescado", + slug="hasta-luego-y-gracias", + ), + ), + ], ) ``` @@ -5254,7 +7066,7 @@ client.forms.update_submission(
-**form_submission_id:** `str` — Unique identifier for a Form Submission +**collection_id:** `str` — Unique identifier for a Collection
@@ -5262,7 +7074,7 @@ client.forms.update_submission(
-**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Any]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set +**items:** `typing.Optional[typing.Sequence[CollectionItemWithIdInput]]`
@@ -5282,8 +7094,7 @@ client.forms.update_submission(
-## Users -
client.users.list(...) +
client.collections.items.create_items(...)
@@ -5295,7 +7106,13 @@ client.forms.update_submission(
-Get a list of users for a site

Required scope | `users:read` +Create an item or multiple items in a CMS Collection across multiple corresponding locales. + +**Notes:** + - This endpoint can create up to 100 items in a request. + - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. + +Required scope | `CMS:write`
@@ -5310,13 +7127,25 @@ Get a list of users for a site

Required scope | `users:read`
```python -from webflow.client import Webflow +from webflow import Webflow +from webflow.resources.collections.resources.items import SingleCmsItem client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.list( - site_id="site_id", +client.collections.items.create_items( + collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_ids=[ + "66f6e966c9e1dc700a857ca3", + "66f6e966c9e1dc700a857ca4", + "66f6e966c9e1dc700a857ca5", + ], + is_archived=False, + is_draft=False, + field_data=SingleCmsItem( + name="Don’t Panic", + slug="dont-panic", + ), ) ``` @@ -5333,7 +7162,7 @@ client.users.list(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -5341,7 +7170,7 @@ client.users.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**field_data:** `CreateBulkCollectionItemRequestBodyFieldData`
@@ -5349,7 +7178,7 @@ client.users.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**cms_locale_ids:** `typing.Optional[typing.Sequence[str]]` — Array of identifiers for the locales where the item will be created
@@ -5357,13 +7186,15 @@ client.users.list(
-**sort:** `typing.Optional[UsersListRequestSort]` - -Sort string to use when ordering users +**is_archived:** `typing.Optional[bool]` — Indicates whether the item is archived. + +
+
-Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). +
+
-Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) +**is_draft:** `typing.Optional[bool]` — Indicates whether the item is in draft state.
@@ -5383,7 +7214,7 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-
client.users.get(...) +
client.collections.items.get_item(...)
@@ -5395,7 +7226,9 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-Get a User by ID

Required scope | `users:read` +Get details of a selected Collection Item. + +Required scope | `CMS:read`
@@ -5410,14 +7243,14 @@ Get a User by ID

Required scope | `users:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.get( - site_id="site_id", - user_id="user_id", +client.collections.items.get_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) ``` @@ -5434,7 +7267,7 @@ client.users.get(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -5442,7 +7275,15 @@ client.users.get(
-**user_id:** `str` — Unique identifier for a User +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string.
@@ -5462,7 +7303,7 @@ client.users.get(
-
client.users.delete(...) +
client.collections.items.delete_item(...)
@@ -5474,7 +7315,9 @@ client.users.get(
-Delete a User by ID

Required scope | `users:write` +Delete an Item from a Collection. This endpoint does not currently support bulk deletion. + +Required scope | `CMS:write`
@@ -5489,14 +7332,14 @@ Delete a User by ID

Required scope | `users:write`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.delete( - site_id="site_id", - user_id="user_id", +client.collections.items.delete_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) ``` @@ -5513,7 +7356,7 @@ client.users.delete(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -5521,7 +7364,15 @@ client.users.delete(
-**user_id:** `str` — Unique identifier for a User +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string.
@@ -5541,7 +7392,7 @@ client.users.delete(
-
client.users.update(...) +
client.collections.items.update_item(...)
@@ -5553,9 +7404,9 @@ client.users.delete(
-Update a User by ID

Required scope | `users:write` +Update a selected Item in a Collection. - +Required scope | `CMS:write`
@@ -5570,21 +7421,20 @@ Update a User by ID

Required scope | `users:write`
```python -from webflow import UsersUpdateRequestData -from webflow.client import Webflow +from webflow import CollectionItemPatchSingleFieldData, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.update( - site_id="site_id", - user_id="user_id", - data=UsersUpdateRequestData( - name="Some One", - accept_privacy=False, - accept_communications=False, +client.collections.items.update_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, + field_data=CollectionItemPatchSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", ), - access_groups=["webflowers", "platinum", "free-tier"], ) ``` @@ -5601,7 +7451,7 @@ client.users.update(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -5609,7 +7459,7 @@ client.users.update(
-**user_id:** `str` — Unique identifier for a User +**item_id:** `str` — Unique identifier for an Item
@@ -5617,7 +7467,7 @@ client.users.update(
-**data:** `typing.Optional[UsersUpdateRequestData]` +**id:** `typing.Optional[str]` — Unique identifier for the Item
@@ -5625,8 +7475,7 @@ client.users.update(
-**access_groups:** `typing.Optional[typing.Sequence[str]]` — An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. - +**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item
@@ -5634,71 +7483,31 @@ client.users.update(
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. +**last_published:** `typing.Optional[str]` — The date the item was last published
-
-
- - - - -
- -
client.users.invite(...) -
-
- -#### 📝 Description - -
-
-Create and invite a user with an email address. The user will be sent and invite via email, which they will need to accept in order to join paid Access Groups.

Required scope | `users:write` -
-
+**last_updated:** `typing.Optional[str]` — The date the item was last updated +
-#### 🔌 Usage - -
-
-
-```python -from webflow.client import Webflow - -client = Webflow( - access_token="YOUR_ACCESS_TOKEN", -) -client.users.invite( - site_id="site_id", - email="some.one@home.com", - access_groups=["webflowers"], -) - -``` -
-
+**created_on:** `typing.Optional[str]` — The date the item was created +
-#### ⚙️ Parameters - -
-
-
-**site_id:** `str` — Unique identifier for a Site +**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived
@@ -5706,7 +7515,7 @@ client.users.invite(
-**email:** `str` — Email address of user to send invite to +**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft
@@ -5714,8 +7523,7 @@ client.users.invite(
-**access_groups:** `typing.Optional[typing.Sequence[str]]` — An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. - +**field_data:** `typing.Optional[CollectionItemPatchSingleFieldData]`
@@ -5735,8 +7543,7 @@ client.users.invite(
-## AccessGroups -
client.access_groups.list(...) +
client.collections.items.get_item_live(...)
@@ -5748,7 +7555,9 @@ client.users.invite(
-Get a list of access groups for a site

Required scope | `users:read` +Get details of a selected Collection live Item. + +Required scope | `CMS:read`
@@ -5763,13 +7572,14 @@ Get a list of access groups for a site

Required scope | `users:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.access_groups.list( - site_id="site_id", +client.collections.items.get_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) ``` @@ -5786,15 +7596,7 @@ client.access_groups.list(
-**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- -**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**collection_id:** `str` — Unique identifier for a Collection
@@ -5802,7 +7604,7 @@ client.access_groups.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**item_id:** `str` — Unique identifier for an Item
@@ -5810,10 +7612,7 @@ client.access_groups.list(
-**sort:** `typing.Optional[AccessGroupsListRequestSort]` - -Sort string to use when ordering access groups -Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string.
@@ -5833,8 +7632,7 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-## Products -
client.products.list(...) +
client.collections.items.delete_item_live(...)
@@ -5846,9 +7644,11 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-Retrieve all products for a site. Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. +Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. -Required scope | `ecommerce:read` +This endpoint does not currently support bulk deletion. + +Required scope | `CMS:write`
@@ -5863,13 +7663,14 @@ Required scope | `ecommerce:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.list( - site_id="site_id", +client.collections.items.delete_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) ``` @@ -5886,7 +7687,7 @@ client.products.list(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -5894,7 +7695,7 @@ client.products.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**item_id:** `str` — Unique identifier for an Item
@@ -5902,7 +7703,7 @@ client.products.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string.
@@ -5922,7 +7723,7 @@ client.products.list(
-
client.products.create(...) +
client.collections.items.update_item_live(...)
@@ -5934,15 +7735,9 @@ client.products.list(
-Creating a new Product involves creating both a Product and a SKU, since a Product Item has to have, at minimum, a single SKU. - -In order to create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large - you'll need to create `sku-properties`. In our T-shirt example, a single `sku-property` would be Color. Within that property, we'll need to list out the various colors a T-shirt could be as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. - -Once, you've created a Product and its `sku-properties` with `enum` values, you can create your default SKU, which will automatically be a combination of the first `sku-properties` you've created. In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. After you've created your product, you can create additional SKUs using the Create SKU endpoint - -Upon creation, the default product type will be `Advanced`. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. +Update a selected live Item in a Collection. The updates for this Item will be published to the live site. -Required scope | `ecommerce:write` +Required scope | `CMS:write`
@@ -5957,13 +7752,20 @@ Required scope | `ecommerce:write`
```python -from webflow.client import Webflow +from webflow import CollectionItemPatchSingleFieldData, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.create( - site_id="site_id", +client.collections.items.update_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, + field_data=CollectionItemPatchSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", + ), ) ``` @@ -5980,7 +7782,7 @@ client.products.create(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -5988,7 +7790,7 @@ client.products.create(
-**publish_status:** `typing.Optional[PublishStatus]` +**item_id:** `str` — Unique identifier for an Item
@@ -5996,7 +7798,7 @@ client.products.create(
-**product:** `typing.Optional[Product]` +**id:** `typing.Optional[str]` — Unique identifier for the Item
@@ -6004,7 +7806,55 @@ client.products.create(
-**sku:** `typing.Optional[Sku]` +**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item + +
+
+ +
+
+ +**last_published:** `typing.Optional[str]` — The date the item was last published + +
+
+ +
+
+ +**last_updated:** `typing.Optional[str]` — The date the item was last updated + +
+
+ +
+
+ +**created_on:** `typing.Optional[str]` — The date the item was created + +
+
+ +
+
+ +**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived + +
+
+ +
+
+ +**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft + +
+
+ +
+
+ +**field_data:** `typing.Optional[CollectionItemPatchSingleFieldData]`
@@ -6024,7 +7874,7 @@ client.products.create(
-
client.products.get(...) +
client.collections.items.publish_item(...)
@@ -6036,9 +7886,9 @@ client.products.create(
-Retrieve a single product by its id. All of its SKUs will also be retrieved. +Publish an item or multiple items. -Required scope | `ecommerce:read` +Required scope | `cms:write`
@@ -6053,14 +7903,14 @@ Required scope | `ecommerce:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.get( - site_id="site_id", - product_id="product_id", +client.collections.items.publish_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_ids=["itemIds"], ) ``` @@ -6077,7 +7927,7 @@ client.products.get(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -6085,7 +7935,7 @@ client.products.get(
-**product_id:** `str` — Unique identifier for a Product +**item_ids:** `typing.Sequence[str]`
@@ -6105,7 +7955,8 @@ client.products.get(
-
client.products.update(...) +## Pages Scripts +
client.pages.scripts.get_custom_code(...)
@@ -6117,9 +7968,15 @@ client.products.get(
-Updating an existing Product will set the product type to `Advanced`. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. +Get all registered scripts that have been applied to a specific Page. -Required scope | `ecommerce:write` +In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered +to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate +`custom_code` endpoints. + +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + +Required scope | `custom_code:read`
@@ -6134,14 +7991,13 @@ Required scope | `ecommerce:write`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.update( - site_id="site_id", - product_id="product_id", +client.pages.scripts.get_custom_code( + page_id="63c720f9347c2139b248e552", ) ``` @@ -6158,39 +8014,7 @@ client.products.update(
-**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- -**product_id:** `str` — Unique identifier for a Product - -
-
- -
-
- -**publish_status:** `typing.Optional[PublishStatus]` - -
-
- -
-
- -**product:** `typing.Optional[Product]` - -
-
- -
-
- -**sku:** `typing.Optional[Sku]` +**page_id:** `str` — Unique identifier for a Page
@@ -6210,7 +8034,7 @@ client.products.update(
-
client.products.create_sku(...) +
client.pages.scripts.upsert_custom_code(...)
@@ -6222,11 +8046,17 @@ client.products.update(
-Create additional SKUs to cover every variant of your Product. The Default SKU already counts as one of the variants. +Add a registered script to a Page. -Creating additional SKUs will set the product type to `Advanced` for the product associated with the SKUs. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. +In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered +to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate +`custom_code` endpoints. -Required scope | `ecommerce:write` +A site can have a maximum of 800 registered scripts. + +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + +Required scope | `custom_code:write`
@@ -6241,16 +8071,26 @@ Required scope | `ecommerce:write`
```python -from webflow import Sku -from webflow.client import Webflow +from webflow import ScriptApply, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.create_sku( - site_id="site_id", - product_id="product_id", - skus=[Sku()], +client.pages.scripts.upsert_custom_code( + page_id="63c720f9347c2139b248e552", + scripts=[ + ScriptApply( + id="cms_slider", + location="header", + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location="header", + version="0.0.1", + ), + ], ) ``` @@ -6267,7 +8107,7 @@ client.products.create_sku(
-**site_id:** `str` — Unique identifier for a Site +**page_id:** `str` — Unique identifier for a Page
@@ -6275,7 +8115,7 @@ client.products.create_sku(
-**product_id:** `str` — Unique identifier for a Product +**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page
@@ -6283,7 +8123,7 @@ client.products.create_sku(
-**skus:** `typing.Sequence[Sku]` — An array of the SKU data your are adding +**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated
@@ -6291,7 +8131,7 @@ client.products.create_sku(
-**publish_status:** `typing.Optional[PublishStatus]` +**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created
@@ -6311,7 +8151,7 @@ client.products.create_sku(
-
client.products.update_sku(...) +
client.pages.scripts.delete_custom_code(...)
@@ -6323,9 +8163,15 @@ client.products.create_sku(
-Updating an existing SKU will set the product type to `Advanced` for the product associated with the SKU. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. +Delete the custom code block that an app has created for a page -Required scope | `ecommerce:write` +In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered +to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate +`custom_code` endpoints. + +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + +Required scope | `custom_code:write`
@@ -6340,17 +8186,13 @@ Required scope | `ecommerce:write`
```python -from webflow import Sku -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.update_sku( - site_id="site_id", - product_id="product_id", - sku_id="sku_id", - sku=Sku(), +client.pages.scripts.delete_custom_code( + page_id="63c720f9347c2139b248e552", ) ``` @@ -6367,7 +8209,7 @@ client.products.update_sku(
-**site_id:** `str` — Unique identifier for a Site +**page_id:** `str` — Unique identifier for a Page
@@ -6375,31 +8217,75 @@ client.products.update_sku(
-**product_id:** `str` — Unique identifier for a Product +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+ + + + +
+## Sites Redirects +
client.sites.redirects.list(...)
-**sku_id:** `str` — Unique identifier for a SKU - +#### 📝 Description + +
+
+ +
+
+ +Fetch a list of all URL redirect rules configured for a specific site. + +Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + + +Required scope: `sites:read` +
+
+#### 🔌 Usage +
-**sku:** `Sku` - +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.redirects.list( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+#### ⚙️ Parameters +
-**publish_status:** `typing.Optional[PublishStatus]` +
+
+ +**site_id:** `str` — Unique identifier for a Site
@@ -6419,8 +8305,7 @@ client.products.update_sku(
-## Orders -
client.orders.list(...) +
client.sites.redirects.create(...)
@@ -6432,9 +8317,11 @@ client.products.update_sku(
-List all orders created for a given site. +Add a new URL redirection rule to a site. -Required scope | `ecommerce:read` +This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. + +Required scope: `sites:write`
@@ -6449,13 +8336,16 @@ Required scope | `ecommerce:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.list( - site_id="site_id", +client.sites.redirects.create( + site_id="580e63e98c9a982ac9b8b741", + id="42e1a2b7aa1a13f768a0042a", + from_url="/mostly-harmless", + to_url="/earth", ) ``` @@ -6480,7 +8370,7 @@ client.orders.list(
-**status:** `typing.Optional[OrdersListRequestStatus]` — Filter the orders by status +**id:** `typing.Optional[str]` — The ID of the specific redirect rule
@@ -6488,7 +8378,7 @@ client.orders.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**from_url:** `typing.Optional[str]` — The source URL path that will be redirected.
@@ -6496,7 +8386,7 @@ client.orders.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected.
@@ -6516,7 +8406,7 @@ client.orders.list(
-
client.orders.get(...) +
client.sites.redirects.delete(...)
@@ -6528,9 +8418,9 @@ client.orders.list(
-Retrieve a single product by its id. All of its SKUs will also be retrieved. - -Required scope | `ecommerce:read` +Remove a URL redirection rule from a site. +This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. +Required scope: `sites:write`
@@ -6545,14 +8435,14 @@ Required scope | `ecommerce:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.get( - site_id="site_id", - order_id="order_id", +client.sites.redirects.delete( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", ) ``` @@ -6577,7 +8467,7 @@ client.orders.get(
-**order_id:** `str` — Unique identifier for an Order +**redirect_id:** `str` — Unique identifier site rediect
@@ -6597,7 +8487,7 @@ client.orders.get(
-
client.orders.update(...) +
client.sites.redirects.update(...)
@@ -6609,9 +8499,8 @@ client.orders.get(
-This API lets you update the fields, `comment`, `shippingProvider`, and/or `shippingTracking` for a given order. All three fields can be updated simultaneously or independently. - -Required scope | `ecommerce:write` +Update a URL redirection rule from a site. +Required scope: `sites:write`
@@ -6626,14 +8515,17 @@ Required scope | `ecommerce:write`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.update( - site_id="site_id", - order_id="order_id", +client.sites.redirects.update( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", + id="42e1a2b7aa1a13f768a0042a", + from_url="/mostly-harmless", + to_url="/earth", ) ``` @@ -6658,15 +8550,7 @@ client.orders.update(
-**order_id:** `str` — Unique identifier for an Order - -
-
- -
-
- -**comment:** `typing.Optional[str]` — Arbitrary data for your records +**redirect_id:** `str` — Unique identifier site rediect
@@ -6674,7 +8558,7 @@ client.orders.update(
-**shipping_provider:** `typing.Optional[str]` — Company or method used to ship order +**id:** `typing.Optional[str]` — The ID of the specific redirect rule
@@ -6682,7 +8566,7 @@ client.orders.update(
-**shipping_tracking:** `typing.Optional[str]` — Tracking number for order shipment +**from_url:** `typing.Optional[str]` — The source URL path that will be redirected.
@@ -6690,7 +8574,7 @@ client.orders.update(
-**shipping_tracking_url:** `typing.Optional[str]` — URL to track order shipment +**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected.
@@ -6710,7 +8594,8 @@ client.orders.update(
-
client.orders.update_fulfill(...) +## Sites Plans +
client.sites.plans.get_site_plan(...)
@@ -6722,9 +8607,9 @@ client.orders.update(
-Updates an order's status to fulfilled +Get site plan details for the specified Site. -Required scope | `ecommerce:write` +Required scope | `sites:read`
@@ -6739,14 +8624,13 @@ Required scope | `ecommerce:write`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.update_fulfill( - site_id="site_id", - order_id="order_id", +client.sites.plans.get_site_plan( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -6771,22 +8655,6 @@ client.orders.update_fulfill(
-**order_id:** `str` — Unique identifier for an Order - -
-
- -
-
- -**send_order_fulfilled_email:** `typing.Optional[bool]` — Whether or not the Order Fulfilled email should be sent - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -6799,7 +8667,8 @@ client.orders.update_fulfill(
-
client.orders.update_unfulfill(...) +## Sites ActivityLogs +
client.sites.activity_logs.list(...)
@@ -6811,9 +8680,7 @@ client.orders.update_fulfill(
-Updates an order's status to unfulfilled - -Required scope | `ecommerce:write` +Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read`
@@ -6828,14 +8695,13 @@ Required scope | `ecommerce:write`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.update_unfulfill( - site_id="site_id", - order_id="order_id", +client.sites.activity_logs.list( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -6860,7 +8726,15 @@ client.orders.update_unfulfill(
-**order_id:** `str` — Unique identifier for an Order +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records
@@ -6880,7 +8754,8 @@ client.orders.update_unfulfill(
-
client.orders.refund(...) +## Sites Scripts +
client.sites.scripts.get_custom_code(...)
@@ -6892,10 +8767,11 @@ client.orders.update_unfulfill(
-This API will reverse a Stripe charge and refund an order back to a -customer. It will also set the order's status to `refunded`. +Get all registered scripts that have been applied to a specific Site. -Required scope | `ecommerce:write` +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + +Required scope | `custom_code:read`
@@ -6910,14 +8786,13 @@ Required scope | `ecommerce:write`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.refund( - site_id="site_id", - order_id="order_id", +client.sites.scripts.get_custom_code( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -6942,22 +8817,6 @@ client.orders.refund(
-**order_id:** `str` — Unique identifier for an Order - -
-
- -
-
- -**reason:** `typing.Optional[OrdersRefundRequestReason]` — The reason for the refund - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -6970,8 +8829,7 @@ client.orders.refund(
-## Inventory -
client.inventory.list(...) +
client.sites.scripts.upsert_custom_code(...)
@@ -6983,9 +8841,15 @@ client.orders.refund(
-List the current inventory levels for a particular SKU item. +Add a registered script to a Site. -Required scope | `ecommerce:read` +In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered +to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate +`custom_code` endpoints. + +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + +Required scope | `custom_code:write`
@@ -7000,14 +8864,26 @@ Required scope | `ecommerce:read`
```python -from webflow.client import Webflow +from webflow import ScriptApply, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.inventory.list( - collection_id="collection_id", - item_id="item_id", +client.sites.scripts.upsert_custom_code( + site_id="580e63e98c9a982ac9b8b741", + scripts=[ + ScriptApply( + id="cms_slider", + location="header", + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location="header", + version="0.0.1", + ), + ], ) ``` @@ -7024,7 +8900,7 @@ client.inventory.list(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -7032,7 +8908,23 @@ client.inventory.list(
-**item_id:** `str` — Unique identifier for an Item +**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page + +
+
+ +
+
+ +**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated + +
+
+ +
+
+ +**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created
@@ -7052,7 +8944,7 @@ client.inventory.list(
-
client.inventory.update(...) +
client.sites.scripts.delete_custom_code(...)
@@ -7064,9 +8956,11 @@ client.inventory.list(
-Updates the current inventory levels for a particular SKU item. Updates may be given in one or two methods, absolutely or incrementally. Absolute updates are done by setting `quantity` directly. Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. +Delete the custom code block that an app created for a Site -Required scope | `ecommerce:write` +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + +Required scope | `custom_code:write`
@@ -7081,16 +8975,13 @@ Required scope | `ecommerce:write`
```python -from webflow import InventoryUpdateRequestInventoryType -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.inventory.update( - collection_id="collection_id", - item_id="item_id", - inventory_type=InventoryUpdateRequestInventoryType.INFINITE, +client.sites.scripts.delete_custom_code( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -7107,39 +8998,7 @@ client.inventory.update(
-**collection_id:** `str` — Unique identifier for a Collection - -
-
- -
-
- -**item_id:** `str` — Unique identifier for an Item - -
-
- -
-
- -**inventory_type:** `InventoryUpdateRequestInventoryType` — infinite or finite - -
-
- -
-
- -**update_quantity:** `typing.Optional[float]` — Adds this quantity to currently store quantity. Can be negative. - -
-
- -
-
- -**quantity:** `typing.Optional[float]` — Immediately sets quantity to this value. +**site_id:** `str` — Unique identifier for a Site
@@ -7159,8 +9018,7 @@ client.inventory.update(
-## Ecommerce -
client.ecommerce.get_settings(...) +
client.sites.scripts.list_custom_code_blocks(...)
@@ -7172,9 +9030,11 @@ client.inventory.update(
-Retrieve ecommerce settings for a site. +Get all instances of Custom Code applied to a Site or Pages. -Required scope | `ecommerce:read` +Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + +Required scope | `custom_code:read`
@@ -7189,13 +9049,13 @@ Required scope | `ecommerce:read`
```python -from webflow.client import Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.ecommerce.get_settings( - site_id="site_id", +client.sites.scripts.list_custom_code_blocks( + site_id="580e63e98c9a982ac9b8b741", ) ``` @@ -7220,6 +9080,22 @@ client.ecommerce.get_settings(
+**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
diff --git a/src/webflow/__init__.py b/src/webflow/__init__.py index 45e46b7..0d82d59 100644 --- a/src/webflow/__init__.py +++ b/src/webflow/__init__.py @@ -16,13 +16,31 @@ AuthorizationAuthorizationAuthorizedTo, AuthorizedUser, BadRequestErrorBody, + BulkCollectionItem, + BulkCollectionItemFieldData, Collection, CollectionItem, CollectionItemFieldData, CollectionItemList, + CollectionItemListNoPagination, CollectionItemListPagination, + CollectionItemPatchSingle, + CollectionItemPatchSingleFieldData, + CollectionItemPostSingle, + CollectionItemPostSingleFieldData, + CollectionItemWithIdInput, + CollectionItemWithIdInputFieldData, CollectionList, CollectionListArrayItem, + Component, + ComponentDom, + ComponentInstanceNodePropertyOverridesWrite, + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + ComponentList, + ComponentNode, + ComponentProperties, + ComponentProperty, + ComponentPropertyType, ConflictErrorBody, CustomCodeBlock, CustomCodeBlockType, @@ -34,7 +52,7 @@ DuplicateUserEmail, EcommerceSettings, Error, - ErrorDetailsItem, + ErrorCode, Field, FieldType, ForbiddenErrorBody, @@ -47,18 +65,21 @@ FormSubmission, FormSubmissionList, ImageNode, + ImageNodeImage, InvalidDomain, + InvalidScopes, InventoryItem, InventoryItemInventoryType, ListCustomCodeBlocks, Locale, Locales, - MissingScopes, NoDomains, Node, - NodeType, + Node_ComponentInstance, + Node_Image, + Node_Text, NotEnterprisePlanSite, - OauthScope, + NotEnterprisePlanWorkspace, Order, OrderAddress, OrderAddressJapanType, @@ -78,9 +99,6 @@ OrderTotalsExtrasItem, OrderTotalsExtrasItemType, Page, - PageDetails, - PageDetailsOpenGraph, - PageDetailsSeo, PageList, PageOpenGraph, PageSeo, @@ -93,6 +111,8 @@ ProductFieldDataEcProductType, ProductFieldDataTaxCategory, PublishStatus, + Redirect, + Redirects, RegisteredScriptList, ScriptApply, ScriptApplyList, @@ -100,9 +120,14 @@ Scripts, Site, SiteActivityLogItem, + SiteActivityLogItemEvent, SiteActivityLogItemResourceOperation, SiteActivityLogItemUser, SiteActivityLogResponse, + SiteDataCollectionType, + SitePlan, + SitePlanId, + SitePlanName, Sites, Sku, SkuFieldData, @@ -120,7 +145,10 @@ StripeCardBrand, StripeCardExpires, StripeDetails, + Text, TextNode, + TextNodeText, + TextNodeWrite, TriggerType, User, UserAccessGroupsItem, @@ -132,6 +160,7 @@ UserStatus, UsersNotEnabled, Webhook, + WebhookFilter, WebhookList, ) from .errors import ( @@ -145,17 +174,23 @@ ) from .resources import ( AccessGroupsListRequestSort, - DomWriteNodesItem, + ComponentDomWriteNodesItem, + ComponentPropertiesWritePropertiesItem, + ComponentsUpdateContentResponse, + ComponentsUpdatePropertiesResponse, InventoryUpdateRequestInventoryType, OrdersListRequestStatus, OrdersRefundRequestReason, + PageDomWriteNodesItem, ProductsCreateSkuResponse, + SitesPublishResponse, UpdateStaticContentResponse, UsersListRequestSort, UsersUpdateRequestData, access_groups, assets, collections, + components, ecommerce, forms, inventory, @@ -168,6 +203,7 @@ users, webhooks, ) +from .client import AsyncWebflow, Webflow from .environment import WebflowEnvironment from .version import __version__ @@ -183,19 +219,42 @@ "AssetUploadUploadDetails", "AssetVariant", "Assets", + "AsyncWebflow", "Authorization", "AuthorizationAuthorization", "AuthorizationAuthorizationAuthorizedTo", "AuthorizedUser", "BadRequestError", "BadRequestErrorBody", + "BulkCollectionItem", + "BulkCollectionItemFieldData", "Collection", "CollectionItem", "CollectionItemFieldData", "CollectionItemList", + "CollectionItemListNoPagination", "CollectionItemListPagination", + "CollectionItemPatchSingle", + "CollectionItemPatchSingleFieldData", + "CollectionItemPostSingle", + "CollectionItemPostSingleFieldData", + "CollectionItemWithIdInput", + "CollectionItemWithIdInputFieldData", "CollectionList", "CollectionListArrayItem", + "Component", + "ComponentDom", + "ComponentDomWriteNodesItem", + "ComponentInstanceNodePropertyOverridesWrite", + "ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem", + "ComponentList", + "ComponentNode", + "ComponentProperties", + "ComponentPropertiesWritePropertiesItem", + "ComponentProperty", + "ComponentPropertyType", + "ComponentsUpdateContentResponse", + "ComponentsUpdatePropertiesResponse", "ConflictError", "ConflictErrorBody", "CustomCodeBlock", @@ -203,13 +262,12 @@ "CustomCodeHostedResponse", "CustomCodeInlineResponse", "Dom", - "DomWriteNodesItem", "Domain", "Domains", "DuplicateUserEmail", "EcommerceSettings", "Error", - "ErrorDetailsItem", + "ErrorCode", "Field", "FieldType", "ForbiddenError", @@ -223,21 +281,24 @@ "FormSubmission", "FormSubmissionList", "ImageNode", + "ImageNodeImage", "InternalServerError", "InvalidDomain", + "InvalidScopes", "InventoryItem", "InventoryItemInventoryType", "InventoryUpdateRequestInventoryType", "ListCustomCodeBlocks", "Locale", "Locales", - "MissingScopes", "NoDomains", "Node", - "NodeType", + "Node_ComponentInstance", + "Node_Image", + "Node_Text", "NotEnterprisePlanSite", + "NotEnterprisePlanWorkspace", "NotFoundError", - "OauthScope", "Order", "OrderAddress", "OrderAddressJapanType", @@ -259,9 +320,7 @@ "OrdersListRequestStatus", "OrdersRefundRequestReason", "Page", - "PageDetails", - "PageDetailsOpenGraph", - "PageDetailsSeo", + "PageDomWriteNodesItem", "PageList", "PageOpenGraph", "PageSeo", @@ -275,6 +334,8 @@ "ProductFieldDataTaxCategory", "ProductsCreateSkuResponse", "PublishStatus", + "Redirect", + "Redirects", "RegisteredScriptList", "ScriptApply", "ScriptApplyList", @@ -282,10 +343,16 @@ "Scripts", "Site", "SiteActivityLogItem", + "SiteActivityLogItemEvent", "SiteActivityLogItemResourceOperation", "SiteActivityLogItemUser", "SiteActivityLogResponse", + "SiteDataCollectionType", + "SitePlan", + "SitePlanId", + "SitePlanName", "Sites", + "SitesPublishResponse", "Sku", "SkuFieldData", "SkuFieldDataCompareAtPrice", @@ -302,7 +369,10 @@ "StripeCardBrand", "StripeCardExpires", "StripeDetails", + "Text", "TextNode", + "TextNodeText", + "TextNodeWrite", "TooManyRequestsError", "TriggerType", "UnauthorizedError", @@ -318,13 +388,16 @@ "UsersListRequestSort", "UsersNotEnabled", "UsersUpdateRequestData", + "Webflow", "WebflowEnvironment", "Webhook", + "WebhookFilter", "WebhookList", "__version__", "access_groups", "assets", "collections", + "components", "ecommerce", "forms", "inventory", diff --git a/src/webflow/client.py b/src/webflow/client.py index 2a602d9..90c233d 100644 --- a/src/webflow/client.py +++ b/src/webflow/client.py @@ -1,25 +1,40 @@ # This file was auto-generated by Fern from our API Definition. import typing - -import httpx - -from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .environment import WebflowEnvironment -from .resources.access_groups.client import AccessGroupsClient, AsyncAccessGroupsClient -from .resources.assets.client import AssetsClient, AsyncAssetsClient -from .resources.collections.client import AsyncCollectionsClient, CollectionsClient -from .resources.ecommerce.client import AsyncEcommerceClient, EcommerceClient -from .resources.forms.client import AsyncFormsClient, FormsClient -from .resources.inventory.client import AsyncInventoryClient, InventoryClient -from .resources.orders.client import AsyncOrdersClient, OrdersClient -from .resources.pages.client import AsyncPagesClient, PagesClient -from .resources.products.client import AsyncProductsClient, ProductsClient -from .resources.scripts.client import AsyncScriptsClient, ScriptsClient -from .resources.sites.client import AsyncSitesClient, SitesClient -from .resources.token.client import AsyncTokenClient, TokenClient -from .resources.users.client import AsyncUsersClient, UsersClient -from .resources.webhooks.client import AsyncWebhooksClient, WebhooksClient +import httpx +from .core.client_wrapper import SyncClientWrapper +from .resources.token.client import TokenClient +from .resources.sites.client import SitesClient +from .resources.collections.client import CollectionsClient +from .resources.pages.client import PagesClient +from .resources.components.client import ComponentsClient +from .resources.scripts.client import ScriptsClient +from .resources.assets.client import AssetsClient +from .resources.webhooks.client import WebhooksClient +from .resources.forms.client import FormsClient +from .resources.users.client import UsersClient +from .resources.access_groups.client import AccessGroupsClient +from .resources.products.client import ProductsClient +from .resources.orders.client import OrdersClient +from .resources.inventory.client import InventoryClient +from .resources.ecommerce.client import EcommerceClient +from .core.client_wrapper import AsyncClientWrapper +from .resources.token.client import AsyncTokenClient +from .resources.sites.client import AsyncSitesClient +from .resources.collections.client import AsyncCollectionsClient +from .resources.pages.client import AsyncPagesClient +from .resources.components.client import AsyncComponentsClient +from .resources.scripts.client import AsyncScriptsClient +from .resources.assets.client import AsyncAssetsClient +from .resources.webhooks.client import AsyncWebhooksClient +from .resources.forms.client import AsyncFormsClient +from .resources.users.client import AsyncUsersClient +from .resources.access_groups.client import AsyncAccessGroupsClient +from .resources.products.client import AsyncProductsClient +from .resources.orders.client import AsyncOrdersClient +from .resources.inventory.client import AsyncInventoryClient +from .resources.ecommerce.client import AsyncEcommerceClient class Webflow: @@ -52,7 +67,7 @@ class Webflow: Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -67,7 +82,7 @@ def __init__( access_token: typing.Union[str, typing.Callable[[], str]], timeout: typing.Optional[float] = None, follow_redirects: typing.Optional[bool] = True, - httpx_client: typing.Optional[httpx.Client] = None + httpx_client: typing.Optional[httpx.Client] = None, ): _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None self._client_wrapper = SyncClientWrapper( @@ -84,6 +99,7 @@ def __init__( self.sites = SitesClient(client_wrapper=self._client_wrapper) self.collections = CollectionsClient(client_wrapper=self._client_wrapper) self.pages = PagesClient(client_wrapper=self._client_wrapper) + self.components = ComponentsClient(client_wrapper=self._client_wrapper) self.scripts = ScriptsClient(client_wrapper=self._client_wrapper) self.assets = AssetsClient(client_wrapper=self._client_wrapper) self.webhooks = WebhooksClient(client_wrapper=self._client_wrapper) @@ -126,7 +142,7 @@ class AsyncWebflow: Examples -------- - from webflow.client import AsyncWebflow + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -141,7 +157,7 @@ def __init__( access_token: typing.Union[str, typing.Callable[[], str]], timeout: typing.Optional[float] = None, follow_redirects: typing.Optional[bool] = True, - httpx_client: typing.Optional[httpx.AsyncClient] = None + httpx_client: typing.Optional[httpx.AsyncClient] = None, ): _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None self._client_wrapper = AsyncClientWrapper( @@ -158,6 +174,7 @@ def __init__( self.sites = AsyncSitesClient(client_wrapper=self._client_wrapper) self.collections = AsyncCollectionsClient(client_wrapper=self._client_wrapper) self.pages = AsyncPagesClient(client_wrapper=self._client_wrapper) + self.components = AsyncComponentsClient(client_wrapper=self._client_wrapper) self.scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) self.assets = AsyncAssetsClient(client_wrapper=self._client_wrapper) self.webhooks = AsyncWebhooksClient(client_wrapper=self._client_wrapper) diff --git a/src/webflow/core/__init__.py b/src/webflow/core/__init__.py index 58ad52a..f03aecb 100644 --- a/src/webflow/core/__init__.py +++ b/src/webflow/core/__init__.py @@ -3,28 +3,45 @@ from .api_error import ApiError from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper from .datetime_utils import serialize_datetime -from .file import File, convert_file_dict_to_httpx_tuples +from .file import File, convert_file_dict_to_httpx_tuples, with_content_type from .http_client import AsyncHttpClient, HttpClient from .jsonable_encoder import jsonable_encoder -from .pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from .pydantic_utilities import ( + IS_PYDANTIC_V2, + UniversalBaseModel, + UniversalRootModel, + parse_obj_as, + universal_field_validator, + universal_root_validator, + update_forward_refs, +) from .query_encoder import encode_query from .remove_none_from_dict import remove_none_from_dict from .request_options import RequestOptions +from .serialization import FieldMetadata, convert_and_respect_annotation_metadata __all__ = [ "ApiError", "AsyncClientWrapper", "AsyncHttpClient", "BaseClientWrapper", + "FieldMetadata", "File", "HttpClient", + "IS_PYDANTIC_V2", "RequestOptions", "SyncClientWrapper", + "UniversalBaseModel", + "UniversalRootModel", + "convert_and_respect_annotation_metadata", "convert_file_dict_to_httpx_tuples", - "deep_union_pydantic_dicts", "encode_query", "jsonable_encoder", - "pydantic_v1", + "parse_obj_as", "remove_none_from_dict", "serialize_datetime", + "universal_field_validator", + "universal_root_validator", + "update_forward_refs", + "with_content_type", ] diff --git a/src/webflow/core/client_wrapper.py b/src/webflow/core/client_wrapper.py index f8b1535..1ea63b3 100644 --- a/src/webflow/core/client_wrapper.py +++ b/src/webflow/core/client_wrapper.py @@ -1,10 +1,9 @@ # This file was auto-generated by Fern from our API Definition. import typing - import httpx - -from .http_client import AsyncHttpClient, HttpClient +from .http_client import HttpClient +from .http_client import AsyncHttpClient class BaseClientWrapper: @@ -23,7 +22,7 @@ def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { "X-Fern-Language": "Python", "X-Fern-SDK-Name": "webflow", - "X-Fern-SDK-Version": "1.2.2", + "X-Fern-SDK-Version": "1.2.1", } headers["Authorization"] = f"Bearer {self._get_access_token()}" return headers @@ -53,9 +52,9 @@ def __init__( super().__init__(access_token=access_token, base_url=base_url, timeout=timeout) self.httpx_client = HttpClient( httpx_client=httpx_client, - base_headers=self.get_headers(), - base_timeout=self.get_timeout(), - base_url=self.get_base_url(), + base_headers=self.get_headers, + base_timeout=self.get_timeout, + base_url=self.get_base_url, ) @@ -71,7 +70,7 @@ def __init__( super().__init__(access_token=access_token, base_url=base_url, timeout=timeout) self.httpx_client = AsyncHttpClient( httpx_client=httpx_client, - base_headers=self.get_headers(), - base_timeout=self.get_timeout(), - base_url=self.get_base_url(), + base_headers=self.get_headers, + base_timeout=self.get_timeout, + base_url=self.get_base_url, ) diff --git a/src/webflow/core/file.py b/src/webflow/core/file.py index cb0d40b..44b0d27 100644 --- a/src/webflow/core/file.py +++ b/src/webflow/core/file.py @@ -1,25 +1,30 @@ # This file was auto-generated by Fern from our API Definition. -import typing +from typing import IO, Dict, List, Mapping, Optional, Tuple, Union, cast # File typing inspired by the flexibility of types within the httpx library # https://github.com/encode/httpx/blob/master/httpx/_types.py -FileContent = typing.Union[typing.IO[bytes], bytes, str] -File = typing.Union[ +FileContent = Union[IO[bytes], bytes, str] +File = Union[ # file (or bytes) FileContent, # (filename, file (or bytes)) - typing.Tuple[typing.Optional[str], FileContent], + Tuple[Optional[str], FileContent], # (filename, file (or bytes), content_type) - typing.Tuple[typing.Optional[str], FileContent, typing.Optional[str]], + Tuple[Optional[str], FileContent, Optional[str]], # (filename, file (or bytes), content_type, headers) - typing.Tuple[typing.Optional[str], FileContent, typing.Optional[str], typing.Mapping[str, str]], + Tuple[ + Optional[str], + FileContent, + Optional[str], + Mapping[str, str], + ], ] def convert_file_dict_to_httpx_tuples( - d: typing.Dict[str, typing.Union[File, typing.List[File]]] -) -> typing.List[typing.Tuple[str, File]]: + d: Dict[str, Union[File, List[File]]], +) -> List[Tuple[str, File]]: """ The format we use is a list of tuples, where the first element is the name of the file and the second is the file object. Typically HTTPX wants @@ -36,3 +41,27 @@ def convert_file_dict_to_httpx_tuples( else: httpx_tuples.append((key, file_like)) return httpx_tuples + + +def with_content_type(*, file: File, default_content_type: str) -> File: + """ + This function resolves to the file's content type, if provided, and defaults + to the default_content_type value if not. + """ + if isinstance(file, tuple): + if len(file) == 2: + filename, content = cast(Tuple[Optional[str], FileContent], file) # type: ignore + return (filename, content, default_content_type) + elif len(file) == 3: + filename, content, file_content_type = cast(Tuple[Optional[str], FileContent, Optional[str]], file) # type: ignore + out_content_type = file_content_type or default_content_type + return (filename, content, out_content_type) + elif len(file) == 4: + filename, content, file_content_type, headers = cast( # type: ignore + Tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]], file + ) + out_content_type = file_content_type or default_content_type + return (filename, content, out_content_type, headers) + else: + raise ValueError(f"Unexpected tuple length: {len(file)}") + return (None, file, default_content_type) diff --git a/src/webflow/core/http_client.py b/src/webflow/core/http_client.py index 09c6836..1a1a131 100644 --- a/src/webflow/core/http_client.py +++ b/src/webflow/core/http_client.py @@ -90,7 +90,8 @@ def _should_retry(response: httpx.Response) -> bool: def remove_omit_from_dict( - original: typing.Dict[str, typing.Optional[typing.Any]], omit: typing.Optional[typing.Any] + original: typing.Dict[str, typing.Optional[typing.Any]], + omit: typing.Optional[typing.Any], ) -> typing.Dict[str, typing.Any]: if omit is None: return original @@ -108,7 +109,7 @@ def maybe_filter_request_body( ) -> typing.Optional[typing.Any]: if data is None: return ( - jsonable_encoder(request_options.get("additional_body_parameters", {})) + jsonable_encoder(request_options.get("additional_body_parameters", {})) or {} if request_options is not None else None ) @@ -118,7 +119,7 @@ def maybe_filter_request_body( data_content = { **(jsonable_encoder(remove_omit_from_dict(data, omit))), # type: ignore **( - jsonable_encoder(request_options.get("additional_body_parameters", {})) + jsonable_encoder(request_options.get("additional_body_parameters", {})) or {} if request_options is not None else {} ), @@ -142,7 +143,8 @@ def get_request_body( # If both data and json are None, we send json data in the event extra properties are specified json_body = maybe_filter_request_body(json, request_options, omit) - return json_body, data_body + # If you have an empty JSON body, you should just send None + return (json_body if json_body != {} else None), data_body if data_body != {} else None class HttpClient: @@ -150,9 +152,9 @@ def __init__( self, *, httpx_client: httpx.Client, - base_timeout: typing.Optional[float], - base_headers: typing.Dict[str, str], - base_url: typing.Optional[str] = None, + base_timeout: typing.Callable[[], typing.Optional[float]], + base_headers: typing.Callable[[], typing.Dict[str, str]], + base_url: typing.Optional[typing.Callable[[], str]] = None, ): self.base_url = base_url self.base_timeout = base_timeout @@ -160,7 +162,10 @@ def __init__( self.httpx_client = httpx_client def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str: - base_url = self.base_url if maybe_base_url is None else maybe_base_url + base_url = maybe_base_url + if self.base_url is not None and base_url is None: + base_url = self.base_url() + if base_url is None: raise ValueError("A base_url is required to make this request, please provide one and try again.") return base_url @@ -185,7 +190,7 @@ def request( timeout = ( request_options.get("timeout_in_seconds") if request_options is not None and request_options.get("timeout_in_seconds") is not None - else self.base_timeout + else self.base_timeout() ) json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) @@ -196,9 +201,9 @@ def request( headers=jsonable_encoder( remove_none_from_dict( { - **self.base_headers, + **self.base_headers(), **(headers if headers is not None else {}), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), + **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), } ) ), @@ -209,7 +214,7 @@ def request( { **(params if params is not None else {}), **( - request_options.get("additional_query_parameters", {}) + request_options.get("additional_query_parameters", {}) or {} if request_options is not None else {} ), @@ -222,7 +227,11 @@ def request( json=json_body, data=data_body, content=content, - files=convert_file_dict_to_httpx_tuples(remove_none_from_dict(files)) if files is not None else None, + files=( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit) + else None + ), timeout=timeout, ) @@ -267,7 +276,7 @@ def stream( timeout = ( request_options.get("timeout_in_seconds") if request_options is not None and request_options.get("timeout_in_seconds") is not None - else self.base_timeout + else self.base_timeout() ) json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) @@ -278,7 +287,7 @@ def stream( headers=jsonable_encoder( remove_none_from_dict( { - **self.base_headers, + **self.base_headers(), **(headers if headers is not None else {}), **(request_options.get("additional_headers", {}) if request_options is not None else {}), } @@ -304,7 +313,11 @@ def stream( json=json_body, data=data_body, content=content, - files=convert_file_dict_to_httpx_tuples(remove_none_from_dict(files)) if files is not None else None, + files=( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit) + else None + ), timeout=timeout, ) as stream: yield stream @@ -315,9 +328,9 @@ def __init__( self, *, httpx_client: httpx.AsyncClient, - base_timeout: typing.Optional[float], - base_headers: typing.Dict[str, str], - base_url: typing.Optional[str] = None, + base_timeout: typing.Callable[[], typing.Optional[float]], + base_headers: typing.Callable[[], typing.Dict[str, str]], + base_url: typing.Optional[typing.Callable[[], str]] = None, ): self.base_url = base_url self.base_timeout = base_timeout @@ -325,7 +338,10 @@ def __init__( self.httpx_client = httpx_client def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str: - base_url = self.base_url if maybe_base_url is None else maybe_base_url + base_url = maybe_base_url + if self.base_url is not None and base_url is None: + base_url = self.base_url() + if base_url is None: raise ValueError("A base_url is required to make this request, please provide one and try again.") return base_url @@ -350,7 +366,7 @@ async def request( timeout = ( request_options.get("timeout_in_seconds") if request_options is not None and request_options.get("timeout_in_seconds") is not None - else self.base_timeout + else self.base_timeout() ) json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) @@ -362,9 +378,9 @@ async def request( headers=jsonable_encoder( remove_none_from_dict( { - **self.base_headers, + **self.base_headers(), **(headers if headers is not None else {}), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), + **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), } ) ), @@ -375,7 +391,7 @@ async def request( { **(params if params is not None else {}), **( - request_options.get("additional_query_parameters", {}) + request_options.get("additional_query_parameters", {}) or {} if request_options is not None else {} ), @@ -388,7 +404,11 @@ async def request( json=json_body, data=data_body, content=content, - files=convert_file_dict_to_httpx_tuples(remove_none_from_dict(files)) if files is not None else None, + files=( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if files is not None + else None + ), timeout=timeout, ) @@ -432,7 +452,7 @@ async def stream( timeout = ( request_options.get("timeout_in_seconds") if request_options is not None and request_options.get("timeout_in_seconds") is not None - else self.base_timeout + else self.base_timeout() ) json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) @@ -443,7 +463,7 @@ async def stream( headers=jsonable_encoder( remove_none_from_dict( { - **self.base_headers, + **self.base_headers(), **(headers if headers is not None else {}), **(request_options.get("additional_headers", {}) if request_options is not None else {}), } @@ -469,7 +489,11 @@ async def stream( json=json_body, data=data_body, content=content, - files=convert_file_dict_to_httpx_tuples(remove_none_from_dict(files)) if files is not None else None, + files=( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if files is not None + else None + ), timeout=timeout, ) as stream: yield stream diff --git a/src/webflow/core/jsonable_encoder.py b/src/webflow/core/jsonable_encoder.py index 7f48273..1b631e9 100644 --- a/src/webflow/core/jsonable_encoder.py +++ b/src/webflow/core/jsonable_encoder.py @@ -8,33 +8,27 @@ https://github.com/tiangolo/fastapi/blob/master/fastapi/encoders.py """ +import base64 import dataclasses import datetime as dt -from collections import defaultdict from enum import Enum from pathlib import PurePath from types import GeneratorType -from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union +from typing import Any, Callable, Dict, List, Optional, Set, Union + +import pydantic from .datetime_utils import serialize_datetime -from .pydantic_utilities import pydantic_v1 +from .pydantic_utilities import ( + IS_PYDANTIC_V2, + encode_by_type, + to_jsonable_with_fallback, +) SetIntStr = Set[Union[int, str]] DictIntStrAny = Dict[Union[int, str], Any] -def generate_encoders_by_class_tuples( - type_encoder_map: Dict[Any, Callable[[Any], Any]] -) -> Dict[Callable[[Any], Any], Tuple[Any, ...]]: - encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(tuple) - for type_, encoder in type_encoder_map.items(): - encoders_by_class_tuples[encoder] += (type_,) - return encoders_by_class_tuples - - -encoders_by_class_tuples = generate_encoders_by_class_tuples(pydantic_v1.json.ENCODERS_BY_TYPE) - - def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None) -> Any: custom_encoder = custom_encoder or {} if custom_encoder: @@ -44,17 +38,24 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any] for encoder_type, encoder_instance in custom_encoder.items(): if isinstance(obj, encoder_type): return encoder_instance(obj) - if isinstance(obj, pydantic_v1.BaseModel): - encoder = getattr(obj.__config__, "json_encoders", {}) + if isinstance(obj, pydantic.BaseModel): + if IS_PYDANTIC_V2: + encoder = getattr(obj.model_config, "json_encoders", {}) # type: ignore # Pydantic v2 + else: + encoder = getattr(obj.__config__, "json_encoders", {}) # type: ignore # Pydantic v1 if custom_encoder: encoder.update(custom_encoder) obj_dict = obj.dict(by_alias=True) if "__root__" in obj_dict: obj_dict = obj_dict["__root__"] + if "root" in obj_dict: + obj_dict = obj_dict["root"] return jsonable_encoder(obj_dict, custom_encoder=encoder) if dataclasses.is_dataclass(obj): - obj_dict = dataclasses.asdict(obj) + obj_dict = dataclasses.asdict(obj) # type: ignore return jsonable_encoder(obj_dict, custom_encoder=custom_encoder) + if isinstance(obj, bytes): + return base64.b64encode(obj).decode("utf-8") if isinstance(obj, Enum): return obj.value if isinstance(obj, PurePath): @@ -80,20 +81,21 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any] encoded_list.append(jsonable_encoder(item, custom_encoder=custom_encoder)) return encoded_list - if type(obj) in pydantic_v1.json.ENCODERS_BY_TYPE: - return pydantic_v1.json.ENCODERS_BY_TYPE[type(obj)](obj) - for encoder, classes_tuple in encoders_by_class_tuples.items(): - if isinstance(obj, classes_tuple): - return encoder(obj) + def fallback_serializer(o: Any) -> Any: + attempt_encode = encode_by_type(o) + if attempt_encode is not None: + return attempt_encode - try: - data = dict(obj) - except Exception as e: - errors: List[Exception] = [] - errors.append(e) try: - data = vars(obj) + data = dict(o) except Exception as e: + errors: List[Exception] = [] errors.append(e) - raise ValueError(errors) from e - return jsonable_encoder(data, custom_encoder=custom_encoder) + try: + data = vars(o) + except Exception as e: + errors.append(e) + raise ValueError(errors) from e + return jsonable_encoder(data, custom_encoder=custom_encoder) + + return to_jsonable_with_fallback(obj, fallback_serializer) diff --git a/src/webflow/core/pydantic_utilities.py b/src/webflow/core/pydantic_utilities.py index a72c1a5..ee8f0e4 100644 --- a/src/webflow/core/pydantic_utilities.py +++ b/src/webflow/core/pydantic_utilities.py @@ -1,28 +1,296 @@ # This file was auto-generated by Fern from our API Definition. +# nopycln: file +import datetime as dt import typing +from collections import defaultdict + +import typing_extensions import pydantic +from .datetime_utils import serialize_datetime +from .serialization import convert_and_respect_annotation_metadata + IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.") if IS_PYDANTIC_V2: - import pydantic.v1 as pydantic_v1 # type: ignore # nopycln: import + # isort will try to reformat the comments on these imports, which breaks mypy + # isort: off + from pydantic.v1.datetime_parse import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2 + parse_date as parse_date, + ) + from pydantic.v1.datetime_parse import ( # pyright: ignore[reportMissingImports] # Pydantic v2 + parse_datetime as parse_datetime, + ) + from pydantic.v1.json import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2 + ENCODERS_BY_TYPE as encoders_by_type, + ) + from pydantic.v1.typing import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2 + get_args as get_args, + ) + from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2 + get_origin as get_origin, + ) + from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2 + is_literal_type as is_literal_type, + ) + from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2 + is_union as is_union, + ) + from pydantic.v1.fields import ModelField as ModelField # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2 else: - import pydantic as pydantic_v1 # type: ignore # nopycln: import + from pydantic.datetime_parse import parse_date as parse_date # type: ignore # Pydantic v1 + from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore # Pydantic v1 + from pydantic.fields import ModelField as ModelField # type: ignore # Pydantic v1 + from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore # Pydantic v1 + from pydantic.typing import get_args as get_args # type: ignore # Pydantic v1 + from pydantic.typing import get_origin as get_origin # type: ignore # Pydantic v1 + from pydantic.typing import is_literal_type as is_literal_type # type: ignore # Pydantic v1 + from pydantic.typing import is_union as is_union # type: ignore # Pydantic v1 + + # isort: on + + +T = typing.TypeVar("T") +Model = typing.TypeVar("Model", bound=pydantic.BaseModel) + + +def parse_obj_as(type_: typing.Type[T], object_: typing.Any) -> T: + dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read") + if IS_PYDANTIC_V2: + adapter = pydantic.TypeAdapter(type_) # type: ignore # Pydantic v2 + return adapter.validate_python(dealiased_object) + else: + return pydantic.parse_obj_as(type_, dealiased_object) + + +def to_jsonable_with_fallback( + obj: typing.Any, fallback_serializer: typing.Callable[[typing.Any], typing.Any] +) -> typing.Any: + if IS_PYDANTIC_V2: + from pydantic_core import to_jsonable_python + + return to_jsonable_python(obj, fallback=fallback_serializer) + else: + return fallback_serializer(obj) + + +class UniversalBaseModel(pydantic.BaseModel): + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( + # Allow fields begining with `model_` to be used in the model + protected_namespaces=(), + ) # type: ignore # Pydantic v2 + + @pydantic.model_serializer(mode="wrap", when_used="json") # type: ignore # Pydantic v2 + def serialize_model(self, handler: pydantic.SerializerFunctionWrapHandler) -> typing.Any: # type: ignore # Pydantic v2 + serialized = handler(self) + data = {k: serialize_datetime(v) if isinstance(v, dt.datetime) else v for k, v in serialized.items()} + return data + + else: + + class Config: + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} + + @classmethod + def model_construct( + cls: typing.Type["Model"], _fields_set: typing.Optional[typing.Set[str]] = None, **values: typing.Any + ) -> "Model": + dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read") + return cls.construct(_fields_set, **dealiased_object) + + @classmethod + def construct( + cls: typing.Type["Model"], _fields_set: typing.Optional[typing.Set[str]] = None, **values: typing.Any + ) -> "Model": + dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read") + if IS_PYDANTIC_V2: + return super().model_construct(_fields_set, **dealiased_object) # type: ignore # Pydantic v2 + else: + return super().construct(_fields_set, **dealiased_object) + + def json(self, **kwargs: typing.Any) -> str: + kwargs_with_defaults: typing.Any = { + "by_alias": True, + "exclude_unset": True, + **kwargs, + } + if IS_PYDANTIC_V2: + return super().model_dump_json(**kwargs_with_defaults) # type: ignore # Pydantic v2 + else: + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + """ + Override the default dict method to `exclude_unset` by default. This function patches + `exclude_unset` to work include fields within non-None default values. + """ + # Note: the logic here is multi-plexed given the levers exposed in Pydantic V1 vs V2 + # Pydantic V1's .dict can be extremely slow, so we do not want to call it twice. + # + # We'd ideally do the same for Pydantic V2, but it shells out to a library to serialize models + # that we have less control over, and this is less intrusive than custom serializers for now. + if IS_PYDANTIC_V2: + kwargs_with_defaults_exclude_unset: typing.Any = { + **kwargs, + "by_alias": True, + "exclude_unset": True, + "exclude_none": False, + } + kwargs_with_defaults_exclude_none: typing.Any = { + **kwargs, + "by_alias": True, + "exclude_none": True, + "exclude_unset": False, + } + dict_dump = deep_union_pydantic_dicts( + super().model_dump(**kwargs_with_defaults_exclude_unset), # type: ignore # Pydantic v2 + super().model_dump(**kwargs_with_defaults_exclude_none), # type: ignore # Pydantic v2 + ) + + else: + _fields_set = self.__fields_set__.copy() + + fields = _get_model_fields(self.__class__) + for name, field in fields.items(): + if name not in _fields_set: + default = _get_field_default(field) + + # If the default values are non-null act like they've been set + # This effectively allows exclude_unset to work like exclude_none where + # the latter passes through intentionally set none values. + if default is not None or ("exclude_unset" in kwargs and not kwargs["exclude_unset"]): + _fields_set.add(name) + + if default is not None: + self.__fields_set__.add(name) + + kwargs_with_defaults_exclude_unset_include_fields: typing.Any = { + "by_alias": True, + "exclude_unset": True, + "include": _fields_set, + **kwargs, + } + + dict_dump = super().dict(**kwargs_with_defaults_exclude_unset_include_fields) + + return convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write") + + +def _union_list_of_pydantic_dicts( + source: typing.List[typing.Any], destination: typing.List[typing.Any] +) -> typing.List[typing.Any]: + converted_list: typing.List[typing.Any] = [] + for i, item in enumerate(source): + destination_value = destination[i] # type: ignore + if isinstance(item, dict): + converted_list.append(deep_union_pydantic_dicts(item, destination_value)) + elif isinstance(item, list): + converted_list.append(_union_list_of_pydantic_dicts(item, destination_value)) + else: + converted_list.append(item) + return converted_list def deep_union_pydantic_dicts( source: typing.Dict[str, typing.Any], destination: typing.Dict[str, typing.Any] ) -> typing.Dict[str, typing.Any]: for key, value in source.items(): + node = destination.setdefault(key, {}) if isinstance(value, dict): - node = destination.setdefault(key, {}) deep_union_pydantic_dicts(value, node) + # Note: we do not do this same processing for sets given we do not have sets of models + # and given the sets are unordered, the processing of the set and matching objects would + # be non-trivial. + elif isinstance(value, list): + destination[key] = _union_list_of_pydantic_dicts(value, node) else: destination[key] = value return destination -__all__ = ["pydantic_v1"] +if IS_PYDANTIC_V2: + + class V2RootModel(UniversalBaseModel, pydantic.RootModel): # type: ignore # Pydantic v2 + pass + + UniversalRootModel: typing_extensions.TypeAlias = V2RootModel # type: ignore +else: + UniversalRootModel: typing_extensions.TypeAlias = UniversalBaseModel # type: ignore + + +def encode_by_type(o: typing.Any) -> typing.Any: + encoders_by_class_tuples: typing.Dict[typing.Callable[[typing.Any], typing.Any], typing.Tuple[typing.Any, ...]] = ( + defaultdict(tuple) + ) + for type_, encoder in encoders_by_type.items(): + encoders_by_class_tuples[encoder] += (type_,) + + if type(o) in encoders_by_type: + return encoders_by_type[type(o)](o) + for encoder, classes_tuple in encoders_by_class_tuples.items(): + if isinstance(o, classes_tuple): + return encoder(o) + + +def update_forward_refs(model: typing.Type["Model"], **localns: typing.Any) -> None: + if IS_PYDANTIC_V2: + model.model_rebuild(raise_errors=False) # type: ignore # Pydantic v2 + else: + model.update_forward_refs(**localns) + + +# Mirrors Pydantic's internal typing +AnyCallable = typing.Callable[..., typing.Any] + + +def universal_root_validator( + pre: bool = False, +) -> typing.Callable[[AnyCallable], AnyCallable]: + def decorator(func: AnyCallable) -> AnyCallable: + if IS_PYDANTIC_V2: + return pydantic.model_validator(mode="before" if pre else "after")(func) # type: ignore # Pydantic v2 + else: + return pydantic.root_validator(pre=pre)(func) # type: ignore # Pydantic v1 + + return decorator + + +def universal_field_validator(field_name: str, pre: bool = False) -> typing.Callable[[AnyCallable], AnyCallable]: + def decorator(func: AnyCallable) -> AnyCallable: + if IS_PYDANTIC_V2: + return pydantic.field_validator(field_name, mode="before" if pre else "after")(func) # type: ignore # Pydantic v2 + else: + return pydantic.validator(field_name, pre=pre)(func) # type: ignore # Pydantic v1 + + return decorator + + +PydanticField = typing.Union[ModelField, pydantic.fields.FieldInfo] + + +def _get_model_fields( + model: typing.Type["Model"], +) -> typing.Mapping[str, PydanticField]: + if IS_PYDANTIC_V2: + return model.model_fields # type: ignore # Pydantic v2 + else: + return model.__fields__ # type: ignore # Pydantic v1 + + +def _get_field_default(field: PydanticField) -> typing.Any: + try: + value = field.get_default() # type: ignore # Pydantic < v1.10.15 + except: + value = field.default + if IS_PYDANTIC_V2: + from pydantic_core import PydanticUndefined + + if value == PydanticUndefined: + return None + return value + return value diff --git a/src/webflow/core/query_encoder.py b/src/webflow/core/query_encoder.py index 1f5f766..3183001 100644 --- a/src/webflow/core/query_encoder.py +++ b/src/webflow/core/query_encoder.py @@ -1,33 +1,58 @@ # This file was auto-generated by Fern from our API Definition. -from collections import ChainMap -from typing import Any, Dict, Optional +from typing import Any, Dict, List, Optional, Tuple -from .pydantic_utilities import pydantic_v1 +import pydantic # Flattens dicts to be of the form {"key[subkey][subkey2]": value} where value is not a dict -def traverse_query_dict(dict_flat: Dict[str, Any], key_prefix: Optional[str] = None) -> Dict[str, Any]: - result = {} +def traverse_query_dict(dict_flat: Dict[str, Any], key_prefix: Optional[str] = None) -> List[Tuple[str, Any]]: + result = [] for k, v in dict_flat.items(): key = f"{key_prefix}[{k}]" if key_prefix is not None else k if isinstance(v, dict): - result.update(traverse_query_dict(v, key)) + result.extend(traverse_query_dict(v, key)) + elif isinstance(v, list): + for arr_v in v: + if isinstance(arr_v, dict): + result.extend(traverse_query_dict(arr_v, key)) + else: + result.append((key, arr_v)) else: - result[key] = v + result.append((key, v)) return result -def single_query_encoder(query_key: str, query_value: Any) -> Dict[str, Any]: - if isinstance(query_value, pydantic_v1.BaseModel) or isinstance(query_value, dict): - if isinstance(query_value, pydantic_v1.BaseModel): +def single_query_encoder(query_key: str, query_value: Any) -> List[Tuple[str, Any]]: + if isinstance(query_value, pydantic.BaseModel) or isinstance(query_value, dict): + if isinstance(query_value, pydantic.BaseModel): obj_dict = query_value.dict(by_alias=True) else: obj_dict = query_value return traverse_query_dict(obj_dict, query_key) + elif isinstance(query_value, list): + encoded_values: List[Tuple[str, Any]] = [] + for value in query_value: + if isinstance(value, pydantic.BaseModel) or isinstance(value, dict): + if isinstance(value, pydantic.BaseModel): + obj_dict = value.dict(by_alias=True) + elif isinstance(value, dict): + obj_dict = value - return {query_key: query_value} + encoded_values.extend(single_query_encoder(query_key, obj_dict)) + else: + encoded_values.append((query_key, value)) + return encoded_values -def encode_query(query: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]: - return dict(ChainMap(*[single_query_encoder(k, v) for k, v in query.items()])) if query is not None else None + return [(query_key, query_value)] + + +def encode_query(query: Optional[Dict[str, Any]]) -> Optional[List[Tuple[str, Any]]]: + if query is None: + return None + + encoded_query = [] + for k, v in query.items(): + encoded_query.extend(single_query_encoder(k, v)) + return encoded_query diff --git a/src/webflow/core/request_options.py b/src/webflow/core/request_options.py index d0bf0db..1b38804 100644 --- a/src/webflow/core/request_options.py +++ b/src/webflow/core/request_options.py @@ -23,6 +23,8 @@ class RequestOptions(typing.TypedDict, total=False): - additional_query_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's query parameters dict - additional_body_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's body parameters dict + + - chunk_size: int. The size, in bytes, to process each chunk of data being streamed back within the response. This equates to leveraging `chunk_size` within `requests` or `httpx`, and is only leveraged for file downloads. """ timeout_in_seconds: NotRequired[int] @@ -30,3 +32,4 @@ class RequestOptions(typing.TypedDict, total=False): additional_headers: NotRequired[typing.Dict[str, typing.Any]] additional_query_parameters: NotRequired[typing.Dict[str, typing.Any]] additional_body_parameters: NotRequired[typing.Dict[str, typing.Any]] + chunk_size: NotRequired[int] diff --git a/src/webflow/core/serialization.py b/src/webflow/core/serialization.py new file mode 100644 index 0000000..cb5dcbf --- /dev/null +++ b/src/webflow/core/serialization.py @@ -0,0 +1,272 @@ +# This file was auto-generated by Fern from our API Definition. + +import collections +import inspect +import typing + +import typing_extensions + +import pydantic + + +class FieldMetadata: + """ + Metadata class used to annotate fields to provide additional information. + + Example: + class MyDict(TypedDict): + field: typing.Annotated[str, FieldMetadata(alias="field_name")] + + Will serialize: `{"field": "value"}` + To: `{"field_name": "value"}` + """ + + alias: str + + def __init__(self, *, alias: str) -> None: + self.alias = alias + + +def convert_and_respect_annotation_metadata( + *, + object_: typing.Any, + annotation: typing.Any, + inner_type: typing.Optional[typing.Any] = None, + direction: typing.Literal["read", "write"], +) -> typing.Any: + """ + Respect the metadata annotations on a field, such as aliasing. This function effectively + manipulates the dict-form of an object to respect the metadata annotations. This is primarily used for + TypedDicts, which cannot support aliasing out of the box, and can be extended for additional + utilities, such as defaults. + + Parameters + ---------- + object_ : typing.Any + + annotation : type + The type we're looking to apply typing annotations from + + inner_type : typing.Optional[type] + + Returns + ------- + typing.Any + """ + + if object_ is None: + return None + if inner_type is None: + inner_type = annotation + + clean_type = _remove_annotations(inner_type) + # Pydantic models + if ( + inspect.isclass(clean_type) + and issubclass(clean_type, pydantic.BaseModel) + and isinstance(object_, typing.Mapping) + ): + return _convert_mapping(object_, clean_type, direction) + # TypedDicts + if typing_extensions.is_typeddict(clean_type) and isinstance(object_, typing.Mapping): + return _convert_mapping(object_, clean_type, direction) + + if ( + typing_extensions.get_origin(clean_type) == typing.Dict + or typing_extensions.get_origin(clean_type) == dict + or clean_type == typing.Dict + ) and isinstance(object_, typing.Dict): + key_type = typing_extensions.get_args(clean_type)[0] + value_type = typing_extensions.get_args(clean_type)[1] + + return { + key: convert_and_respect_annotation_metadata( + object_=value, + annotation=annotation, + inner_type=value_type, + direction=direction, + ) + for key, value in object_.items() + } + + # If you're iterating on a string, do not bother to coerce it to a sequence. + if not isinstance(object_, str): + if ( + typing_extensions.get_origin(clean_type) == typing.Set + or typing_extensions.get_origin(clean_type) == set + or clean_type == typing.Set + ) and isinstance(object_, typing.Set): + inner_type = typing_extensions.get_args(clean_type)[0] + return { + convert_and_respect_annotation_metadata( + object_=item, + annotation=annotation, + inner_type=inner_type, + direction=direction, + ) + for item in object_ + } + elif ( + ( + typing_extensions.get_origin(clean_type) == typing.List + or typing_extensions.get_origin(clean_type) == list + or clean_type == typing.List + ) + and isinstance(object_, typing.List) + ) or ( + ( + typing_extensions.get_origin(clean_type) == typing.Sequence + or typing_extensions.get_origin(clean_type) == collections.abc.Sequence + or clean_type == typing.Sequence + ) + and isinstance(object_, typing.Sequence) + ): + inner_type = typing_extensions.get_args(clean_type)[0] + return [ + convert_and_respect_annotation_metadata( + object_=item, + annotation=annotation, + inner_type=inner_type, + direction=direction, + ) + for item in object_ + ] + + if typing_extensions.get_origin(clean_type) == typing.Union: + # We should be able to ~relatively~ safely try to convert keys against all + # member types in the union, the edge case here is if one member aliases a field + # of the same name to a different name from another member + # Or if another member aliases a field of the same name that another member does not. + for member in typing_extensions.get_args(clean_type): + object_ = convert_and_respect_annotation_metadata( + object_=object_, + annotation=annotation, + inner_type=member, + direction=direction, + ) + return object_ + + annotated_type = _get_annotation(annotation) + if annotated_type is None: + return object_ + + # If the object is not a TypedDict, a Union, or other container (list, set, sequence, etc.) + # Then we can safely call it on the recursive conversion. + return object_ + + +def _convert_mapping( + object_: typing.Mapping[str, object], + expected_type: typing.Any, + direction: typing.Literal["read", "write"], +) -> typing.Mapping[str, object]: + converted_object: typing.Dict[str, object] = {} + annotations = typing_extensions.get_type_hints(expected_type, include_extras=True) + aliases_to_field_names = _get_alias_to_field_name(annotations) + for key, value in object_.items(): + if direction == "read" and key in aliases_to_field_names: + dealiased_key = aliases_to_field_names.get(key) + if dealiased_key is not None: + type_ = annotations.get(dealiased_key) + else: + type_ = annotations.get(key) + # Note you can't get the annotation by the field name if you're in read mode, so you must check the aliases map + # + # So this is effectively saying if we're in write mode, and we don't have a type, or if we're in read mode and we don't have an alias + # then we can just pass the value through as is + if type_ is None: + converted_object[key] = value + elif direction == "read" and key not in aliases_to_field_names: + converted_object[key] = convert_and_respect_annotation_metadata( + object_=value, annotation=type_, direction=direction + ) + else: + converted_object[_alias_key(key, type_, direction, aliases_to_field_names)] = ( + convert_and_respect_annotation_metadata(object_=value, annotation=type_, direction=direction) + ) + return converted_object + + +def _get_annotation(type_: typing.Any) -> typing.Optional[typing.Any]: + maybe_annotated_type = typing_extensions.get_origin(type_) + if maybe_annotated_type is None: + return None + + if maybe_annotated_type == typing_extensions.NotRequired: + type_ = typing_extensions.get_args(type_)[0] + maybe_annotated_type = typing_extensions.get_origin(type_) + + if maybe_annotated_type == typing_extensions.Annotated: + return type_ + + return None + + +def _remove_annotations(type_: typing.Any) -> typing.Any: + maybe_annotated_type = typing_extensions.get_origin(type_) + if maybe_annotated_type is None: + return type_ + + if maybe_annotated_type == typing_extensions.NotRequired: + return _remove_annotations(typing_extensions.get_args(type_)[0]) + + if maybe_annotated_type == typing_extensions.Annotated: + return _remove_annotations(typing_extensions.get_args(type_)[0]) + + return type_ + + +def get_alias_to_field_mapping(type_: typing.Any) -> typing.Dict[str, str]: + annotations = typing_extensions.get_type_hints(type_, include_extras=True) + return _get_alias_to_field_name(annotations) + + +def get_field_to_alias_mapping(type_: typing.Any) -> typing.Dict[str, str]: + annotations = typing_extensions.get_type_hints(type_, include_extras=True) + return _get_field_to_alias_name(annotations) + + +def _get_alias_to_field_name( + field_to_hint: typing.Dict[str, typing.Any], +) -> typing.Dict[str, str]: + aliases = {} + for field, hint in field_to_hint.items(): + maybe_alias = _get_alias_from_type(hint) + if maybe_alias is not None: + aliases[maybe_alias] = field + return aliases + + +def _get_field_to_alias_name( + field_to_hint: typing.Dict[str, typing.Any], +) -> typing.Dict[str, str]: + aliases = {} + for field, hint in field_to_hint.items(): + maybe_alias = _get_alias_from_type(hint) + if maybe_alias is not None: + aliases[field] = maybe_alias + return aliases + + +def _get_alias_from_type(type_: typing.Any) -> typing.Optional[str]: + maybe_annotated_type = _get_annotation(type_) + + if maybe_annotated_type is not None: + # The actual annotations are 1 onward, the first is the annotated type + annotations = typing_extensions.get_args(maybe_annotated_type)[1:] + + for annotation in annotations: + if isinstance(annotation, FieldMetadata) and annotation.alias is not None: + return annotation.alias + return None + + +def _alias_key( + key: str, + type_: typing.Any, + direction: typing.Literal["read", "write"], + aliases_to_field_names: typing.Dict[str, str], +) -> str: + if direction == "read": + return aliases_to_field_names.get(key, key) + return _get_alias_from_type(type_=type_) or key diff --git a/src/webflow/errors/bad_request_error.py b/src/webflow/errors/bad_request_error.py index 44a05f4..9c13c61 100644 --- a/src/webflow/errors/bad_request_error.py +++ b/src/webflow/errors/bad_request_error.py @@ -1,10 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -import typing - from ..core.api_error import ApiError +import typing class BadRequestError(ApiError): - def __init__(self, body: typing.Any): + def __init__(self, body: typing.Optional[typing.Any]): super().__init__(status_code=400, body=body) diff --git a/src/webflow/errors/conflict_error.py b/src/webflow/errors/conflict_error.py index 416399a..666bd2b 100644 --- a/src/webflow/errors/conflict_error.py +++ b/src/webflow/errors/conflict_error.py @@ -1,10 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -import typing - from ..core.api_error import ApiError +import typing class ConflictError(ApiError): - def __init__(self, body: typing.Any): + def __init__(self, body: typing.Optional[typing.Any]): super().__init__(status_code=409, body=body) diff --git a/src/webflow/errors/forbidden_error.py b/src/webflow/errors/forbidden_error.py index 3f237b5..d17eb4b 100644 --- a/src/webflow/errors/forbidden_error.py +++ b/src/webflow/errors/forbidden_error.py @@ -1,10 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -import typing - from ..core.api_error import ApiError +import typing class ForbiddenError(ApiError): - def __init__(self, body: typing.Any): + def __init__(self, body: typing.Optional[typing.Any]): super().__init__(status_code=403, body=body) diff --git a/src/webflow/errors/internal_server_error.py b/src/webflow/errors/internal_server_error.py index c2764d6..c5dcb4a 100644 --- a/src/webflow/errors/internal_server_error.py +++ b/src/webflow/errors/internal_server_error.py @@ -1,10 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -import typing - from ..core.api_error import ApiError +from ..types.error import Error class InternalServerError(ApiError): - def __init__(self, body: typing.Any): + def __init__(self, body: Error): super().__init__(status_code=500, body=body) diff --git a/src/webflow/errors/not_found_error.py b/src/webflow/errors/not_found_error.py index 4405a19..307aa67 100644 --- a/src/webflow/errors/not_found_error.py +++ b/src/webflow/errors/not_found_error.py @@ -1,10 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -import typing - from ..core.api_error import ApiError +from ..types.error import Error class NotFoundError(ApiError): - def __init__(self, body: typing.Any): + def __init__(self, body: Error): super().__init__(status_code=404, body=body) diff --git a/src/webflow/errors/too_many_requests_error.py b/src/webflow/errors/too_many_requests_error.py index 3bbbb0d..c2b3b10 100644 --- a/src/webflow/errors/too_many_requests_error.py +++ b/src/webflow/errors/too_many_requests_error.py @@ -1,10 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -import typing - from ..core.api_error import ApiError +from ..types.error import Error class TooManyRequestsError(ApiError): - def __init__(self, body: typing.Any): + def __init__(self, body: Error): super().__init__(status_code=429, body=body) diff --git a/src/webflow/errors/unauthorized_error.py b/src/webflow/errors/unauthorized_error.py index e5c83f6..bba82e4 100644 --- a/src/webflow/errors/unauthorized_error.py +++ b/src/webflow/errors/unauthorized_error.py @@ -1,10 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -import typing - from ..core.api_error import ApiError +from ..types.error import Error class UnauthorizedError(ApiError): - def __init__(self, body: typing.Any): + def __init__(self, body: Error): super().__init__(status_code=401, body=body) diff --git a/src/webflow/resources/__init__.py b/src/webflow/resources/__init__.py index 91d1d63..9122eee 100644 --- a/src/webflow/resources/__init__.py +++ b/src/webflow/resources/__init__.py @@ -4,6 +4,7 @@ access_groups, assets, collections, + components, ecommerce, forms, inventory, @@ -17,25 +18,38 @@ webhooks, ) from .access_groups import AccessGroupsListRequestSort +from .components import ( + ComponentDomWriteNodesItem, + ComponentPropertiesWritePropertiesItem, + ComponentsUpdateContentResponse, + ComponentsUpdatePropertiesResponse, +) from .inventory import InventoryUpdateRequestInventoryType from .orders import OrdersListRequestStatus, OrdersRefundRequestReason -from .pages import DomWriteNodesItem, UpdateStaticContentResponse +from .pages import PageDomWriteNodesItem, UpdateStaticContentResponse from .products import ProductsCreateSkuResponse +from .sites import SitesPublishResponse from .users import UsersListRequestSort, UsersUpdateRequestData __all__ = [ "AccessGroupsListRequestSort", - "DomWriteNodesItem", + "ComponentDomWriteNodesItem", + "ComponentPropertiesWritePropertiesItem", + "ComponentsUpdateContentResponse", + "ComponentsUpdatePropertiesResponse", "InventoryUpdateRequestInventoryType", "OrdersListRequestStatus", "OrdersRefundRequestReason", + "PageDomWriteNodesItem", "ProductsCreateSkuResponse", + "SitesPublishResponse", "UpdateStaticContentResponse", "UsersListRequestSort", "UsersUpdateRequestData", "access_groups", "assets", "collections", + "components", "ecommerce", "forms", "inventory", diff --git a/src/webflow/resources/access_groups/client.py b/src/webflow/resources/access_groups/client.py index 2f0e14f..ee7668a 100644 --- a/src/webflow/resources/access_groups/client.py +++ b/src/webflow/resources/access_groups/client.py @@ -1,21 +1,22 @@ # This file was auto-generated by Fern from our API Definition. +from ...core.client_wrapper import SyncClientWrapper import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from .types.access_groups_list_request_sort import AccessGroupsListRequestSort from ...core.request_options import RequestOptions +from ...types.access_group_list import AccessGroupList +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.forbidden_error import ForbiddenError -from ...errors.internal_server_error import InternalServerError from ...errors.not_found_error import NotFoundError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.access_group_list import AccessGroupList -from .types.access_groups_list_request_sort import AccessGroupsListRequestSort +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper class AccessGroupsClient: @@ -32,7 +33,9 @@ def list( request_options: typing.Optional[RequestOptions] = None, ) -> AccessGroupList: """ - Get a list of access groups for a site

Required scope | `users:read` + Get a list of access groups for a site + + Required scope | `users:read` Parameters ---------- @@ -59,36 +62,94 @@ def list( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.access_groups.list( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/accessgroups", method="GET", - params={"offset": offset, "limit": limit, "sort": sort}, + params={ + "offset": offset, + "limit": limit, + "sort": sort, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AccessGroupList, _response.json()) # type: ignore + return typing.cast( + AccessGroupList, + parse_obj_as( + type_=AccessGroupList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -109,7 +170,9 @@ async def list( request_options: typing.Optional[RequestOptions] = None, ) -> AccessGroupList: """ - Get a list of access groups for a site

Required scope | `users:read` + Get a list of access groups for a site + + Required scope | `users:read` Parameters ---------- @@ -136,36 +199,102 @@ async def list( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.access_groups.list( - site_id="site_id", - ) + + + async def main() -> None: + await client.access_groups.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/accessgroups", method="GET", - params={"offset": offset, "limit": limit, "sort": sort}, + params={ + "offset": offset, + "limit": limit, + "sort": sort, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AccessGroupList, _response.json()) # type: ignore + return typing.cast( + AccessGroupList, + parse_obj_as( + type_=AccessGroupList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/access_groups/types/access_groups_list_request_sort.py b/src/webflow/resources/access_groups/types/access_groups_list_request_sort.py index 1a5d034..074583a 100644 --- a/src/webflow/resources/access_groups/types/access_groups_list_request_sort.py +++ b/src/webflow/resources/access_groups/types/access_groups_list_request_sort.py @@ -1,26 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class AccessGroupsListRequestSort(str, enum.Enum): - CREATED_ON_ASCENDING = "CreatedOn" - """ - Sorts users in ascending order based on their created date - """ - - CREATED_ON_DESCENDING = "-CreatedOn" - """ - Sorts users in descending order based on their created date - """ - - def visit( - self, created_on_ascending: typing.Callable[[], T_Result], created_on_descending: typing.Callable[[], T_Result] - ) -> T_Result: - if self is AccessGroupsListRequestSort.CREATED_ON_ASCENDING: - return created_on_ascending() - if self is AccessGroupsListRequestSort.CREATED_ON_DESCENDING: - return created_on_descending() +AccessGroupsListRequestSort = typing.Union[typing.Literal["CreatedOn", "-CreatedOn"], typing.Any] diff --git a/src/webflow/resources/assets/client.py b/src/webflow/resources/assets/client.py index 131d573..61e141a 100644 --- a/src/webflow/resources/assets/client.py +++ b/src/webflow/resources/assets/client.py @@ -1,23 +1,24 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from ...core.client_wrapper import SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.assets import Assets +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError -from ...errors.internal_server_error import InternalServerError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.not_found_error import NotFoundError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError +from ...types.asset_upload import AssetUpload from ...types.asset import Asset -from ...types.asset_folder import AssetFolder from ...types.asset_folder_list import AssetFolderList -from ...types.asset_upload import AssetUpload -from ...types.assets import Assets +from ...types.asset_folder import AssetFolder +from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -29,7 +30,9 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Assets: """ - List assets for a given site

Required scope | `assets:read` + List assets for a given site + + Required scope | `assets:read` Parameters ---------- @@ -46,31 +49,79 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.assets.list( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/assets", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/assets", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Assets, _response.json()) # type: ignore + return typing.cast( + Assets, + parse_obj_as( + type_=Assets, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -86,7 +137,15 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> AssetUpload: """ - Create a new asset entry.

This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) request to the `uploadUrl` with the `uploadDetails` object as your header information in the request.

Required scope | `assets:write` + Create a new asset entry. + + + This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. + You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) + request to the `uploadUrl` with the `uploadDetails` object as your header information in the request. + + + Required scope | `assets:write` Parameters ---------- @@ -94,13 +153,13 @@ def create( Unique identifier for a Site file_name : str - file name including file extension + File name including file extension. File names must be less than 100 characters. file_hash : str MD5 hash of the file parent_folder : typing.Optional[str] - id of the Asset folder (optional) + ID of the Asset folder (optional) request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -112,13 +171,13 @@ def create( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.assets.create( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", file_name="file.png", file_hash="3c7d87c9575702bc3b1e991f4d3c638e", ) @@ -126,23 +185,76 @@ def create( _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/assets", method="POST", - json={"fileName": file_name, "fileHash": file_hash, "parentFolder": parent_folder}, + json={ + "fileName": file_name, + "fileHash": file_hash, + "parentFolder": parent_folder, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AssetUpload, _response.json()) # type: ignore + return typing.cast( + AssetUpload, + parse_obj_as( + type_=AssetUpload, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -150,7 +262,9 @@ def create( def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Asset: """ - Get an Asset

Required scope | `assets:read` + Get an Asset + + Required scope | `assets:read` Parameters ---------- @@ -167,31 +281,79 @@ def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.assets.get( - asset_id="asset_id", + asset_id="580e63fc8c9a982ac9b8b745", ) """ _response = self._client_wrapper.httpx_client.request( - f"assets/{jsonable_encoder(asset_id)}", method="GET", request_options=request_options + f"assets/{jsonable_encoder(asset_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Asset, _response.json()) # type: ignore + return typing.cast( + Asset, + parse_obj_as( + type_=Asset, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -201,6 +363,8 @@ def delete(self, asset_id: str, *, request_options: typing.Optional[RequestOptio """ Delete an Asset + Required Scope: `assets: write` + Parameters ---------- asset_id : str @@ -215,49 +379,101 @@ def delete(self, asset_id: str, *, request_options: typing.Optional[RequestOptio Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.assets.delete( - asset_id="asset_id", + asset_id="580e63fc8c9a982ac9b8b745", ) """ _response = self._client_wrapper.httpx_client.request( - f"assets/{jsonable_encoder(asset_id)}", method="DELETE", request_options=request_options + f"assets/{jsonable_encoder(asset_id)}", + method="DELETE", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) def update( - self, asset_id: str, *, display_name: str, request_options: typing.Optional[RequestOptions] = None + self, + asset_id: str, + *, + locale_id: typing.Optional[str] = OMIT, + display_name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, ) -> Asset: """ - Update an Asset

Required scope | `assets:write` + Update an Asset + + Required scope | `assets:write` Parameters ---------- asset_id : str Unique identifier for an Asset on a site - display_name : str - file name including file extension + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + display_name : typing.Optional[str] + A human readable name for the asset request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -269,36 +485,87 @@ def update( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.assets.update( - asset_id="asset_id", - display_name="bulldoze.png", + asset_id="580e63fc8c9a982ac9b8b745", ) """ _response = self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", method="PATCH", - json={"displayName": display_name}, + json={ + "localeId": locale_id, + "displayName": display_name, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Asset, _response.json()) # type: ignore + return typing.cast( + Asset, + parse_obj_as( + type_=Asset, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -306,7 +573,9 @@ def update( def list_folders(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AssetFolderList: """ - List Asset Folders within a given site

Required scope | `assets:read` + List Asset Folders within a given site + + Required scope | `assets:read` Parameters ---------- @@ -323,31 +592,79 @@ def list_folders(self, site_id: str, *, request_options: typing.Optional[Request Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.assets.list_folders( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/asset_folders", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/asset_folders", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AssetFolderList, _response.json()) # type: ignore + return typing.cast( + AssetFolderList, + parse_obj_as( + type_=AssetFolderList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -362,7 +679,9 @@ def create_folder( request_options: typing.Optional[RequestOptions] = None, ) -> AssetFolder: """ - Create an Asset Folder within a given site

Required scope | `assets:write` + Create an Asset Folder within a given site + + Required scope | `assets:write` Parameters ---------- @@ -385,36 +704,88 @@ def create_folder( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.assets.create_folder( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", display_name="my asset folder", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/asset_folders", method="POST", - json={"displayName": display_name, "parentFolder": parent_folder}, + json={ + "displayName": display_name, + "parentFolder": parent_folder, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AssetFolder, _response.json()) # type: ignore + return typing.cast( + AssetFolder, + parse_obj_as( + type_=AssetFolder, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -424,7 +795,9 @@ def get_folder( self, asset_folder_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> AssetFolder: """ - Get details about a specific Asset Folder

Required scope | `assets:read` + Get details about a specific Asset Folder + + Required scope | `assets:read` Parameters ---------- @@ -441,31 +814,79 @@ def get_folder( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.assets.get_folder( - asset_folder_id="asset_folder_id", + asset_folder_id="6390c49774a71f0e3c1a08ee", ) """ _response = self._client_wrapper.httpx_client.request( - f"asset_folders/{jsonable_encoder(asset_folder_id)}", method="GET", request_options=request_options + f"asset_folders/{jsonable_encoder(asset_folder_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AssetFolder, _response.json()) # type: ignore + return typing.cast( + AssetFolder, + parse_obj_as( + type_=AssetFolder, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -478,7 +899,9 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): async def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Assets: """ - List assets for a given site

Required scope | `assets:read` + List assets for a given site + + Required scope | `assets:read` Parameters ---------- @@ -495,31 +918,87 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.assets.list( - site_id="site_id", - ) + + + async def main() -> None: + await client.assets.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/assets", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/assets", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Assets, _response.json()) # type: ignore + return typing.cast( + Assets, + parse_obj_as( + type_=Assets, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -535,7 +1014,15 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> AssetUpload: """ - Create a new asset entry.

This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) request to the `uploadUrl` with the `uploadDetails` object as your header information in the request.

Required scope | `assets:write` + Create a new asset entry. + + + This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. + You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) + request to the `uploadUrl` with the `uploadDetails` object as your header information in the request. + + + Required scope | `assets:write` Parameters ---------- @@ -543,13 +1030,13 @@ async def create( Unique identifier for a Site file_name : str - file name including file extension + File name including file extension. File names must be less than 100 characters. file_hash : str MD5 hash of the file parent_folder : typing.Optional[str] - id of the Asset folder (optional) + ID of the Asset folder (optional) request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -561,37 +1048,98 @@ async def create( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.assets.create( - site_id="site_id", - file_name="file.png", - file_hash="3c7d87c9575702bc3b1e991f4d3c638e", - ) + + + async def main() -> None: + await client.assets.create( + site_id="580e63e98c9a982ac9b8b741", + file_name="file.png", + file_hash="3c7d87c9575702bc3b1e991f4d3c638e", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/assets", method="POST", - json={"fileName": file_name, "fileHash": file_hash, "parentFolder": parent_folder}, + json={ + "fileName": file_name, + "fileHash": file_hash, + "parentFolder": parent_folder, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AssetUpload, _response.json()) # type: ignore + return typing.cast( + AssetUpload, + parse_obj_as( + type_=AssetUpload, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -599,7 +1147,9 @@ async def create( async def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Asset: """ - Get an Asset

Required scope | `assets:read` + Get an Asset + + Required scope | `assets:read` Parameters ---------- @@ -616,31 +1166,87 @@ async def get(self, asset_id: str, *, request_options: typing.Optional[RequestOp Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.assets.get( - asset_id="asset_id", - ) + + + async def main() -> None: + await client.assets.get( + asset_id="580e63fc8c9a982ac9b8b745", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"assets/{jsonable_encoder(asset_id)}", method="GET", request_options=request_options + f"assets/{jsonable_encoder(asset_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Asset, _response.json()) # type: ignore + return typing.cast( + Asset, + parse_obj_as( + type_=Asset, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -650,6 +1256,8 @@ async def delete(self, asset_id: str, *, request_options: typing.Optional[Reques """ Delete an Asset + Required Scope: `assets: write` + Parameters ---------- asset_id : str @@ -664,49 +1272,109 @@ async def delete(self, asset_id: str, *, request_options: typing.Optional[Reques Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.assets.delete( - asset_id="asset_id", - ) + + + async def main() -> None: + await client.assets.delete( + asset_id="580e63fc8c9a982ac9b8b745", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"assets/{jsonable_encoder(asset_id)}", method="DELETE", request_options=request_options + f"assets/{jsonable_encoder(asset_id)}", + method="DELETE", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) async def update( - self, asset_id: str, *, display_name: str, request_options: typing.Optional[RequestOptions] = None + self, + asset_id: str, + *, + locale_id: typing.Optional[str] = OMIT, + display_name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, ) -> Asset: """ - Update an Asset

Required scope | `assets:write` + Update an Asset + + Required scope | `assets:write` Parameters ---------- asset_id : str Unique identifier for an Asset on a site - display_name : str - file name including file extension + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + display_name : typing.Optional[str] + A human readable name for the asset request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -718,36 +1386,95 @@ async def update( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.assets.update( - asset_id="asset_id", - display_name="bulldoze.png", - ) + + + async def main() -> None: + await client.assets.update( + asset_id="580e63fc8c9a982ac9b8b745", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", method="PATCH", - json={"displayName": display_name}, + json={ + "localeId": locale_id, + "displayName": display_name, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Asset, _response.json()) # type: ignore + return typing.cast( + Asset, + parse_obj_as( + type_=Asset, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -757,7 +1484,9 @@ async def list_folders( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> AssetFolderList: """ - List Asset Folders within a given site

Required scope | `assets:read` + List Asset Folders within a given site + + Required scope | `assets:read` Parameters ---------- @@ -774,31 +1503,87 @@ async def list_folders( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.assets.list_folders( - site_id="site_id", - ) + + + async def main() -> None: + await client.assets.list_folders( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/asset_folders", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/asset_folders", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AssetFolderList, _response.json()) # type: ignore + return typing.cast( + AssetFolderList, + parse_obj_as( + type_=AssetFolderList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -813,7 +1598,9 @@ async def create_folder( request_options: typing.Optional[RequestOptions] = None, ) -> AssetFolder: """ - Create an Asset Folder within a given site

Required scope | `assets:write` + Create an Asset Folder within a given site + + Required scope | `assets:write` Parameters ---------- @@ -836,36 +1623,96 @@ async def create_folder( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.assets.create_folder( - site_id="site_id", - display_name="my asset folder", - ) + + + async def main() -> None: + await client.assets.create_folder( + site_id="580e63e98c9a982ac9b8b741", + display_name="my asset folder", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/asset_folders", method="POST", - json={"displayName": display_name, "parentFolder": parent_folder}, + json={ + "displayName": display_name, + "parentFolder": parent_folder, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AssetFolder, _response.json()) # type: ignore + return typing.cast( + AssetFolder, + parse_obj_as( + type_=AssetFolder, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -875,7 +1722,9 @@ async def get_folder( self, asset_folder_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> AssetFolder: """ - Get details about a specific Asset Folder

Required scope | `assets:read` + Get details about a specific Asset Folder + + Required scope | `assets:read` Parameters ---------- @@ -892,31 +1741,87 @@ async def get_folder( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.assets.get_folder( - asset_folder_id="asset_folder_id", - ) + + + async def main() -> None: + await client.assets.get_folder( + asset_folder_id="6390c49774a71f0e3c1a08ee", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"asset_folders/{jsonable_encoder(asset_folder_id)}", method="GET", request_options=request_options + f"asset_folders/{jsonable_encoder(asset_folder_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AssetFolder, _response.json()) # type: ignore + return typing.cast( + AssetFolder, + parse_obj_as( + type_=AssetFolder, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/collections/__init__.py b/src/webflow/resources/collections/__init__.py index a029bd0..cb6aaf8 100644 --- a/src/webflow/resources/collections/__init__.py +++ b/src/webflow/resources/collections/__init__.py @@ -1,23 +1,41 @@ # This file was auto-generated by Fern from our API Definition. from .resources import ( - BulkCollectionItemFieldData, + CreateBulkCollectionItemRequestBodyFieldData, + CreateBulkCollectionItemRequestBodyFieldDataItem, FieldCreateType, + ItemsCreateItemLiveRequest, + ItemsCreateItemRequest, + ItemsDeleteItemsLiveRequestItemsItem, + ItemsDeleteItemsRequestItemsItem, ItemsListItemsLiveRequestSortBy, ItemsListItemsLiveRequestSortOrder, ItemsListItemsRequestSortBy, ItemsListItemsRequestSortOrder, + ItemsPublishItemResponse, + MultipleItems, + MultipleLiveItems, + SingleCmsItem, fields, items, ) __all__ = [ - "BulkCollectionItemFieldData", + "CreateBulkCollectionItemRequestBodyFieldData", + "CreateBulkCollectionItemRequestBodyFieldDataItem", "FieldCreateType", + "ItemsCreateItemLiveRequest", + "ItemsCreateItemRequest", + "ItemsDeleteItemsLiveRequestItemsItem", + "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemResponse", + "MultipleItems", + "MultipleLiveItems", + "SingleCmsItem", "fields", "items", ] diff --git a/src/webflow/resources/collections/client.py b/src/webflow/resources/collections/client.py index 1d1ba20..1e44aae 100644 --- a/src/webflow/resources/collections/client.py +++ b/src/webflow/resources/collections/client.py @@ -1,22 +1,25 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from ...core.client_wrapper import SyncClientWrapper +from .resources.fields.client import FieldsClient +from .resources.items.client import ItemsClient from ...core.request_options import RequestOptions +from ...types.collection_list import CollectionList +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError -from ...errors.internal_server_error import InternalServerError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.not_found_error import NotFoundError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError from ...types.collection import Collection -from ...types.collection_list import CollectionList -from .resources.fields.client import AsyncFieldsClient, FieldsClient -from .resources.items.client import AsyncItemsClient, ItemsClient +from ...core.client_wrapper import AsyncClientWrapper +from .resources.fields.client import AsyncFieldsClient +from .resources.items.client import AsyncItemsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -30,7 +33,9 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> CollectionList: """ - List of all Collections within a Site.

Required scope | `cms:read` + List of all Collections within a Site. + + Required scope | `cms:read` Parameters ---------- @@ -47,31 +52,79 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.list( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/collections", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/collections", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionList, _response.json()) # type: ignore + return typing.cast( + CollectionList, + parse_obj_as( + type_=CollectionList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -87,7 +140,9 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> Collection: """ - Create a Collection for a site.

Required scope | `cms:write` + Create a Collection for a site. + + Required scope | `cms:write` Parameters ---------- @@ -113,13 +168,13 @@ def create( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.create( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", display_name="Blog Posts", singular_name="Blog Post", slug="posts", @@ -128,23 +183,76 @@ def create( _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/collections", method="POST", - json={"displayName": display_name, "singularName": singular_name, "slug": slug}, + json={ + "displayName": display_name, + "singularName": singular_name, + "slug": slug, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Collection, _response.json()) # type: ignore + return typing.cast( + Collection, + parse_obj_as( + type_=Collection, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -152,7 +260,9 @@ def create( def get(self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Collection: """ - Get the full details of a collection from its ID.

Required scope | `cms:read` + Get the full details of a collection from its ID. + + Required scope | `cms:read` Parameters ---------- @@ -169,98 +279,95 @@ def get(self, collection_id: str, *, request_options: typing.Optional[RequestOpt Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.get( - collection_id="collection_id", + collection_id="580e63fc8c9a982ac9b8b745", ) """ _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}", method="GET", request_options=request_options + f"collections/{jsonable_encoder(collection_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Collection, _response.json()) # type: ignore + return typing.cast( + Collection, + parse_obj_as( + type_=Collection, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - def delete_collection(self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: - """ - Delete a collection using its ID.

Required scope | `cms:write` - - Parameters - ---------- - collection_id : str - Unique identifier for a Collection - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from webflow.client import Webflow - - client = Webflow( - access_token="YOUR_ACCESS_TOKEN", - ) - client.collections.delete_collection( - collection_id="collection_id", - ) + def delete(self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}", method="DELETE", request_options=request_options - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + Delete a collection using its ID. - def delete( - self, collection_id: str, field_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Delete a custom field in a collection. This endpoint does not currently support bulk deletion.

Required scope | `cms:write` + Required scope | `cms:write` Parameters ---------- collection_id : str Unique identifier for a Collection - field_id : str - Unique identifier for a Field in a collection - request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -270,18 +377,17 @@ def delete( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.delete( - collection_id="collection_id", - field_id="field_id", + collection_id="580e63fc8c9a982ac9b8b745", ) """ _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + f"collections/{jsonable_encoder(collection_id)}", method="DELETE", request_options=request_options, ) @@ -289,15 +395,55 @@ def delete( if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -312,7 +458,9 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): async def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> CollectionList: """ - List of all Collections within a Site.

Required scope | `cms:read` + List of all Collections within a Site. + + Required scope | `cms:read` Parameters ---------- @@ -329,31 +477,87 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.list( - site_id="site_id", - ) + + + async def main() -> None: + await client.collections.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/collections", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/collections", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionList, _response.json()) # type: ignore + return typing.cast( + CollectionList, + parse_obj_as( + type_=CollectionList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -369,7 +573,9 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> Collection: """ - Create a Collection for a site.

Required scope | `cms:write` + Create a Collection for a site. + + Required scope | `cms:write` Parameters ---------- @@ -395,38 +601,99 @@ async def create( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.create( - site_id="site_id", - display_name="Blog Posts", - singular_name="Blog Post", - slug="posts", - ) + + + async def main() -> None: + await client.collections.create( + site_id="580e63e98c9a982ac9b8b741", + display_name="Blog Posts", + singular_name="Blog Post", + slug="posts", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/collections", method="POST", - json={"displayName": display_name, "singularName": singular_name, "slug": slug}, + json={ + "displayName": display_name, + "singularName": singular_name, + "slug": slug, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Collection, _response.json()) # type: ignore + return typing.cast( + Collection, + parse_obj_as( + type_=Collection, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -434,7 +701,9 @@ async def create( async def get(self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Collection: """ - Get the full details of a collection from its ID.

Required scope | `cms:read` + Get the full details of a collection from its ID. + + Required scope | `cms:read` Parameters ---------- @@ -451,100 +720,103 @@ async def get(self, collection_id: str, *, request_options: typing.Optional[Requ Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.get( - collection_id="collection_id", - ) - """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}", method="GET", request_options=request_options - ) - try: - if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Collection, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) - async def delete_collection( - self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: - """ - Delete a collection using its ID.

Required scope | `cms:write` - Parameters - ---------- - collection_id : str - Unique identifier for a Collection + async def main() -> None: + await client.collections.get( + collection_id="580e63fc8c9a982ac9b8b745", + ) - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - None - - Examples - -------- - from webflow.client import AsyncWebflow - client = AsyncWebflow( - access_token="YOUR_ACCESS_TOKEN", - ) - await client.collections.delete_collection( - collection_id="collection_id", - ) + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}", method="DELETE", request_options=request_options + f"collections/{jsonable_encoder(collection_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return + return typing.cast( + Collection, + parse_obj_as( + type_=Collection, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - async def delete( - self, collection_id: str, field_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: + async def delete(self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete a custom field in a collection. This endpoint does not currently support bulk deletion.

Required scope | `cms:write` + Delete a collection using its ID. + + Required scope | `cms:write` Parameters ---------- collection_id : str Unique identifier for a Collection - field_id : str - Unique identifier for a Field in a collection - request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -554,18 +826,25 @@ async def delete( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.delete( - collection_id="collection_id", - field_id="field_id", - ) + + + async def main() -> None: + await client.collections.delete( + collection_id="580e63fc8c9a982ac9b8b745", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + f"collections/{jsonable_encoder(collection_id)}", method="DELETE", request_options=request_options, ) @@ -573,15 +852,55 @@ async def delete( if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/collections/resources/__init__.py b/src/webflow/resources/collections/resources/__init__.py index 2b2d370..f9325ee 100644 --- a/src/webflow/resources/collections/resources/__init__.py +++ b/src/webflow/resources/collections/resources/__init__.py @@ -3,20 +3,38 @@ from . import fields, items from .fields import FieldCreateType from .items import ( - BulkCollectionItemFieldData, + CreateBulkCollectionItemRequestBodyFieldData, + CreateBulkCollectionItemRequestBodyFieldDataItem, + ItemsCreateItemLiveRequest, + ItemsCreateItemRequest, + ItemsDeleteItemsLiveRequestItemsItem, + ItemsDeleteItemsRequestItemsItem, ItemsListItemsLiveRequestSortBy, ItemsListItemsLiveRequestSortOrder, ItemsListItemsRequestSortBy, ItemsListItemsRequestSortOrder, + ItemsPublishItemResponse, + MultipleItems, + MultipleLiveItems, + SingleCmsItem, ) __all__ = [ - "BulkCollectionItemFieldData", + "CreateBulkCollectionItemRequestBodyFieldData", + "CreateBulkCollectionItemRequestBodyFieldDataItem", "FieldCreateType", + "ItemsCreateItemLiveRequest", + "ItemsCreateItemRequest", + "ItemsDeleteItemsLiveRequestItemsItem", + "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemResponse", + "MultipleItems", + "MultipleLiveItems", + "SingleCmsItem", "fields", "items", ] diff --git a/src/webflow/resources/collections/resources/fields/client.py b/src/webflow/resources/collections/resources/fields/client.py index 710092f..40b66cf 100644 --- a/src/webflow/resources/collections/resources/fields/client.py +++ b/src/webflow/resources/collections/resources/fields/client.py @@ -1,20 +1,21 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from .....core.api_error import ApiError -from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import pydantic_v1 +from .....core.client_wrapper import SyncClientWrapper +from .types.field_create_type import FieldCreateType from .....core.request_options import RequestOptions +from .....types.field import Field +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as from .....errors.bad_request_error import BadRequestError -from .....errors.internal_server_error import InternalServerError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error from .....errors.not_found_error import NotFoundError from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.unauthorized_error import UnauthorizedError -from .....types.field import Field -from .types.field_create_type import FieldCreateType +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -35,7 +36,16 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> Field: """ - Create a custom field in a collection.

Slugs must be all lowercase letters without spaces. If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will convert the slug to lowercase and replace spaces with "-."

Only some field types can be created through the API. This endpoint does not currently support bulk creation.

Required scope | `cms:write` + Create a custom field in a collection. + + Slugs must be all lowercase letters without spaces. + If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will + convert the slug to lowercase and replace spaces with "-." + + Only some field types can be created through the API. + This endpoint does not currently support bulk creation. + + Required scope | `cms:write` Parameters ---------- @@ -64,16 +74,15 @@ def create( Examples -------- - from webflow.client import Webflow - from webflow.resources.collections import FieldCreateType + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.fields.create( - collection_id="collection_id", + collection_id="580e63fc8c9a982ac9b8b745", is_required=False, - type=FieldCreateType.RICH_TEXT, + type="RichText", display_name="Post Body", help_text="Add the body of your post here", ) @@ -81,23 +90,175 @@ def create( _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields", method="POST", - json={"isRequired": is_required, "type": type, "displayName": display_name, "helpText": help_text}, + json={ + "isRequired": is_required, + "type": type, + "displayName": display_name, + "helpText": help_text, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Field, _response.json()) # type: ignore + return typing.cast( + Field, + parse_obj_as( + type_=Field, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete( + self, collection_id: str, field_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Delete a custom field in a collection. This endpoint does not currently support bulk deletion. + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_id : str + Unique identifier for a Field in a collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.collections.fields.delete( + collection_id="580e63fc8c9a982ac9b8b745", + field_id="580e63fc8c9a982ac9b8b745", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -114,7 +275,9 @@ def update( request_options: typing.Optional[RequestOptions] = None, ) -> Field: """ - Update a custom field in a collection.

Required scope | `cms:write` + Update a custom field in a collection. + + Required scope | `cms:write` Parameters ---------- @@ -143,14 +306,14 @@ def update( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.fields.update( - collection_id="collection_id", - field_id="field_id", + collection_id="580e63fc8c9a982ac9b8b745", + field_id="580e63fc8c9a982ac9b8b745", is_required=False, display_name="Post Body", help_text="Add the body of your post here", @@ -159,23 +322,76 @@ def update( _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", method="PATCH", - json={"isRequired": is_required, "displayName": display_name, "helpText": help_text}, + json={ + "isRequired": is_required, + "displayName": display_name, + "helpText": help_text, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Field, _response.json()) # type: ignore + return typing.cast( + Field, + parse_obj_as( + type_=Field, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -197,7 +413,16 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> Field: """ - Create a custom field in a collection.

Slugs must be all lowercase letters without spaces. If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will convert the slug to lowercase and replace spaces with "-."

Only some field types can be created through the API. This endpoint does not currently support bulk creation.

Required scope | `cms:write` + Create a custom field in a collection. + + Slugs must be all lowercase letters without spaces. + If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will + convert the slug to lowercase and replace spaces with "-." + + Only some field types can be created through the API. + This endpoint does not currently support bulk creation. + + Required scope | `cms:write` Parameters ---------- @@ -226,40 +451,207 @@ async def create( Examples -------- - from webflow.client import AsyncWebflow - from webflow.resources.collections import FieldCreateType + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.fields.create( - collection_id="collection_id", - is_required=False, - type=FieldCreateType.RICH_TEXT, - display_name="Post Body", - help_text="Add the body of your post here", - ) + + + async def main() -> None: + await client.collections.fields.create( + collection_id="580e63fc8c9a982ac9b8b745", + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields", method="POST", - json={"isRequired": is_required, "type": type, "displayName": display_name, "helpText": help_text}, + json={ + "isRequired": is_required, + "type": type, + "displayName": display_name, + "helpText": help_text, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Field, _response.json()) # type: ignore + return typing.cast( + Field, + parse_obj_as( + type_=Field, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete( + self, collection_id: str, field_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Delete a custom field in a collection. This endpoint does not currently support bulk deletion. + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_id : str + Unique identifier for a Field in a collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.collections.fields.delete( + collection_id="580e63fc8c9a982ac9b8b745", + field_id="580e63fc8c9a982ac9b8b745", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -276,7 +668,9 @@ async def update( request_options: typing.Optional[RequestOptions] = None, ) -> Field: """ - Update a custom field in a collection.

Required scope | `cms:write` + Update a custom field in a collection. + + Required scope | `cms:write` Parameters ---------- @@ -305,39 +699,100 @@ async def update( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.fields.update( - collection_id="collection_id", - field_id="field_id", - is_required=False, - display_name="Post Body", - help_text="Add the body of your post here", - ) + + + async def main() -> None: + await client.collections.fields.update( + collection_id="580e63fc8c9a982ac9b8b745", + field_id="580e63fc8c9a982ac9b8b745", + is_required=False, + display_name="Post Body", + help_text="Add the body of your post here", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", method="PATCH", - json={"isRequired": is_required, "displayName": display_name, "helpText": help_text}, + json={ + "isRequired": is_required, + "displayName": display_name, + "helpText": help_text, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Field, _response.json()) # type: ignore + return typing.cast( + Field, + parse_obj_as( + type_=Field, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/collections/resources/fields/types/field_create_type.py b/src/webflow/resources/collections/resources/fields/types/field_create_type.py index adf2907..c8ec44b 100644 --- a/src/webflow/resources/collections/resources/fields/types/field_create_type.py +++ b/src/webflow/resources/collections/resources/fields/types/field_create_type.py @@ -1,69 +1,23 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class FieldCreateType(str, enum.Enum): - """ - Choose these appropriate field type for your collection data - """ - - PLAIN_TEXT = "PlainText" - RICH_TEXT = "RichText" - IMAGE = "Image" - MULTI_IMAGE = "MultiImage" - VIDEO = "Video" - LINK = "Link" - EMAIL = "Email" - PHONE = "Phone" - NUMBER = "Number" - DATE_TIME = "DateTime" - SWITCH = "Switch" - COLOR = "Color" - FILE = "File" - - def visit( - self, - plain_text: typing.Callable[[], T_Result], - rich_text: typing.Callable[[], T_Result], - image: typing.Callable[[], T_Result], - multi_image: typing.Callable[[], T_Result], - video: typing.Callable[[], T_Result], - link: typing.Callable[[], T_Result], - email: typing.Callable[[], T_Result], - phone: typing.Callable[[], T_Result], - number: typing.Callable[[], T_Result], - date_time: typing.Callable[[], T_Result], - switch: typing.Callable[[], T_Result], - color: typing.Callable[[], T_Result], - file: typing.Callable[[], T_Result], - ) -> T_Result: - if self is FieldCreateType.PLAIN_TEXT: - return plain_text() - if self is FieldCreateType.RICH_TEXT: - return rich_text() - if self is FieldCreateType.IMAGE: - return image() - if self is FieldCreateType.MULTI_IMAGE: - return multi_image() - if self is FieldCreateType.VIDEO: - return video() - if self is FieldCreateType.LINK: - return link() - if self is FieldCreateType.EMAIL: - return email() - if self is FieldCreateType.PHONE: - return phone() - if self is FieldCreateType.NUMBER: - return number() - if self is FieldCreateType.DATE_TIME: - return date_time() - if self is FieldCreateType.SWITCH: - return switch() - if self is FieldCreateType.COLOR: - return color() - if self is FieldCreateType.FILE: - return file() +FieldCreateType = typing.Union[ + typing.Literal[ + "Color", + "DateTime", + "Email", + "ExtFileRef", + "File", + "Image", + "Link", + "MultiImage", + "Number", + "Phone", + "PlainText", + "RichText", + "Switch", + "Video", + ], + typing.Any, +] diff --git a/src/webflow/resources/collections/resources/items/__init__.py b/src/webflow/resources/collections/resources/items/__init__.py index c8549f0..fbccd1b 100644 --- a/src/webflow/resources/collections/resources/items/__init__.py +++ b/src/webflow/resources/collections/resources/items/__init__.py @@ -1,17 +1,35 @@ # This file was auto-generated by Fern from our API Definition. from .types import ( - BulkCollectionItemFieldData, + CreateBulkCollectionItemRequestBodyFieldData, + CreateBulkCollectionItemRequestBodyFieldDataItem, + ItemsCreateItemLiveRequest, + ItemsCreateItemRequest, + ItemsDeleteItemsLiveRequestItemsItem, + ItemsDeleteItemsRequestItemsItem, ItemsListItemsLiveRequestSortBy, ItemsListItemsLiveRequestSortOrder, ItemsListItemsRequestSortBy, ItemsListItemsRequestSortOrder, + ItemsPublishItemResponse, + MultipleItems, + MultipleLiveItems, + SingleCmsItem, ) __all__ = [ - "BulkCollectionItemFieldData", + "CreateBulkCollectionItemRequestBodyFieldData", + "CreateBulkCollectionItemRequestBodyFieldDataItem", + "ItemsCreateItemLiveRequest", + "ItemsCreateItemRequest", + "ItemsDeleteItemsLiveRequestItemsItem", + "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemResponse", + "MultipleItems", + "MultipleLiveItems", + "SingleCmsItem", ] diff --git a/src/webflow/resources/collections/resources/items/client.py b/src/webflow/resources/collections/resources/items/client.py index 9a51804..47f8f90 100644 --- a/src/webflow/resources/collections/resources/items/client.py +++ b/src/webflow/resources/collections/resources/items/client.py @@ -1,26 +1,37 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from .....core.api_error import ApiError -from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import pydantic_v1 +from .....core.client_wrapper import SyncClientWrapper +from .types.items_list_items_request_sort_by import ItemsListItemsRequestSortBy +from .types.items_list_items_request_sort_order import ItemsListItemsRequestSortOrder from .....core.request_options import RequestOptions +from .....types.collection_item_list import CollectionItemList +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as from .....errors.bad_request_error import BadRequestError -from .....errors.internal_server_error import InternalServerError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error from .....errors.not_found_error import NotFoundError from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.unauthorized_error import UnauthorizedError +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .types.items_create_item_request import ItemsCreateItemRequest from .....types.collection_item import CollectionItem -from .....types.collection_item_field_data import CollectionItemFieldData -from .....types.collection_item_list import CollectionItemList -from .types.bulk_collection_item_field_data import BulkCollectionItemFieldData +from .....core.serialization import convert_and_respect_annotation_metadata +from .types.items_delete_items_request_items_item import ItemsDeleteItemsRequestItemsItem +from .....errors.conflict_error import ConflictError +from .....types.collection_item_with_id_input import CollectionItemWithIdInput from .types.items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy from .types.items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder -from .types.items_list_items_request_sort_by import ItemsListItemsRequestSortBy -from .types.items_list_items_request_sort_order import ItemsListItemsRequestSortOrder +from .types.items_create_item_live_request import ItemsCreateItemLiveRequest +from .types.items_delete_items_live_request_items_item import ItemsDeleteItemsLiveRequestItemsItem +from .....types.collection_item_list_no_pagination import CollectionItemListNoPagination +from .types.create_bulk_collection_item_request_body_field_data import CreateBulkCollectionItemRequestBodyFieldData +from .....types.bulk_collection_item import BulkCollectionItem +from .....types.collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData +from .types.items_publish_item_response import ItemsPublishItemResponse +from .....core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -44,7 +55,9 @@ def list_items( request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemList: """ - List of all Items within a Collection.

Required scope | `CMS:read` + List of all Items within a Collection. + + Required scope | `CMS:read` Parameters ---------- @@ -82,13 +95,13 @@ def list_items( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.list_items( - collection_id="collection_id", + collection_id="580e63fc8c9a982ac9b8b745", ) """ _response = self._client_wrapper.httpx_client.request( @@ -107,17 +120,63 @@ def list_items( ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItemList, _response.json()) # type: ignore + return typing.cast( + CollectionItemList, + parse_obj_as( + type_=CollectionItemList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -127,46 +186,148 @@ def create_item( self, collection_id: str, *, - id: str, - cms_locale_id: typing.Optional[str] = OMIT, - last_published: typing.Optional[str] = OMIT, - last_updated: typing.Optional[str] = OMIT, - created_on: typing.Optional[str] = OMIT, - is_archived: typing.Optional[bool] = OMIT, - is_draft: typing.Optional[bool] = OMIT, - field_data: typing.Optional[CollectionItemFieldData] = OMIT, + request: ItemsCreateItemRequest, request_options: typing.Optional[RequestOptions] = None, - ) -> None: + ) -> CollectionItem: """ - Create Item in a Collection.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` + Create Item(s) in a Collection. + + + To create items across multiple locales, please use [this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + + Required scope | `CMS:write` Parameters ---------- collection_id : str Unique identifier for a Collection - id : str - Unique identifier for the Item + request : ItemsCreateItemRequest - cms_locale_id : typing.Optional[str] - Identifier for the locale of the CMS item + request_options : typing.Optional[RequestOptions] + Request-specific configuration. - last_published : typing.Optional[str] - The date the item was last published + Returns + ------- + CollectionItem + Request was successful - last_updated : typing.Optional[str] - The date the item was last updated + Examples + -------- + from webflow import ( + CollectionItemPostSingle, + CollectionItemPostSingleFieldData, + Webflow, + ) - created_on : typing.Optional[str] - The date the item was created + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.collections.items.create_item( + collection_id="580e63fc8c9a982ac9b8b745", + request=CollectionItemPostSingle( + is_archived=False, + is_draft=False, + field_data=CollectionItemPostSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", + ), + ), + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsCreateItemRequest, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) - is_archived : typing.Optional[bool] - Boolean determining if the Item is set to archived + def delete_items( + self, + collection_id: str, + *, + items: typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Delete Items from a Collection. - is_draft : typing.Optional[bool] - Boolean determining if the Item is set to draft + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be deleted only in the primary locale. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection - field_data : typing.Optional[CollectionItemFieldData] + items : typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -177,39 +338,25 @@ def create_item( Examples -------- - from webflow import CollectionItemFieldData - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) - client.collections.items.create_item( - collection_id="collection_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), + client.collections.items.delete_items( + collection_id="580e63fc8c9a982ac9b8b745", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", - method="POST", + method="DELETE", json={ - "id": id, - "cmsLocaleId": cms_locale_id, - "lastPublished": last_published, - "lastUpdated": last_updated, - "createdOn": created_on, - "isArchived": is_archived, - "isDraft": is_draft, - "fieldData": field_data, + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[ItemsDeleteItemsRequestItemsItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", }, request_options=request_options, omit=OMIT, @@ -218,15 +365,221 @@ def create_item( if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update_items( + self, + collection_id: str, + *, + items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> CollectionItem: + """ + Update a single item or multiple items (up to 100) in a Collection. + + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionItem + Request was successful + + Examples + -------- + from webflow import ( + CollectionItemWithIdInput, + CollectionItemWithIdInputFieldData, + Webflow, + ) + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.collections.items.update_items( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Ne Paniquez Pas", + slug="ne-paniquez-pas", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="No Entrar en Pánico", + slug="no-entrar-en-panico", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Au Revoir et Merci pour Tous les Poissons", + slug="au-revoir-et-merci", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="Hasta Luego y Gracias por Todo el Pescado", + slug="hasta-luego-y-gracias", + ), + ), + ], + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + method="PATCH", + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -246,7 +599,9 @@ def list_items_live( request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemList: """ - List of all live Items within a Collection.

Required scope | `CMS:read` + List of all live Items within a Collection. + + Required scope | `CMS:read` Parameters ---------- @@ -284,13 +639,13 @@ def list_items_live( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.list_items_live( - collection_id="collection_id", + collection_id="580e63fc8c9a982ac9b8b745", ) """ _response = self._client_wrapper.httpx_client.request( @@ -309,17 +664,63 @@ def list_items_live( ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItemList, _response.json()) # type: ignore + return typing.cast( + CollectionItemList, + parse_obj_as( + type_=CollectionItemList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -329,155 +730,145 @@ def create_item_live( self, collection_id: str, *, - id: str, - cms_locale_id: typing.Optional[str] = OMIT, - last_published: typing.Optional[str] = OMIT, - last_updated: typing.Optional[str] = OMIT, - created_on: typing.Optional[str] = OMIT, - is_archived: typing.Optional[bool] = OMIT, - is_draft: typing.Optional[bool] = OMIT, - field_data: typing.Optional[CollectionItemFieldData] = OMIT, + request: ItemsCreateItemLiveRequest, request_options: typing.Optional[RequestOptions] = None, - ) -> None: + ) -> CollectionItem: """ - Create live Item in a Collection. This Item will be published to the live site.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` - - Parameters - ---------- - collection_id : str - Unique identifier for a Collection - - id : str - Unique identifier for the Item - - cms_locale_id : typing.Optional[str] - Identifier for the locale of the CMS item + Create live Item(s) in a Collection. The Item(s) will be published to the live site. - last_published : typing.Optional[str] - The date the item was last published - last_updated : typing.Optional[str] - The date the item was last updated + To create items across multiple locales, [please use this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) - created_on : typing.Optional[str] - The date the item was created - is_archived : typing.Optional[bool] - Boolean determining if the Item is set to archived + Required scope | `CMS:write` - is_draft : typing.Optional[bool] - Boolean determining if the Item is set to draft + Parameters + ---------- + collection_id : str + Unique identifier for a Collection - field_data : typing.Optional[CollectionItemFieldData] + request : ItemsCreateItemLiveRequest request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - None + CollectionItem + Request was successful Examples -------- - from webflow import CollectionItemFieldData - from webflow.client import Webflow + from webflow import CollectionItem, CollectionItemFieldData, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.create_item_live( - collection_id="collection_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", + collection_id="580e63fc8c9a982ac9b8b745", + request=CollectionItem( + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", + ), ), ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", method="POST", - json={ - "id": id, - "cmsLocaleId": cms_locale_id, - "lastPublished": last_published, - "lastUpdated": last_updated, - "createdOn": created_on, - "isArchived": is_archived, - "isDraft": is_draft, - "fieldData": field_data, - }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsCreateItemLiveRequest, direction="write" + ), request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - def create_item_for_multiple_locales( + def delete_items_live( self, collection_id: str, *, - id: str, - cms_locale_ids: typing.Optional[typing.Sequence[str]] = OMIT, - last_published: typing.Optional[str] = OMIT, - last_updated: typing.Optional[str] = OMIT, - created_on: typing.Optional[str] = OMIT, - is_archived: typing.Optional[bool] = OMIT, - is_draft: typing.Optional[bool] = OMIT, - field_data: typing.Optional[BulkCollectionItemFieldData] = OMIT, + items: typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Create single Item in a Collection with multiple corresponding locales.

Required scope | `CMS:write` + Remove an item or multiple items (up to 100 items) from the live site. Deleting published items will unpublish the items from the live site and set them to draft. + + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be unpublished only in the primary locale. + + Required scope | `CMS:write` Parameters ---------- collection_id : str Unique identifier for a Collection - id : str - Unique identifier for the Item - - cms_locale_ids : typing.Optional[typing.Sequence[str]] - Array of identifiers for the locales where the item will be created - - last_published : typing.Optional[str] - The date the item was last published - - last_updated : typing.Optional[str] - The date the item was last updated - - created_on : typing.Optional[str] - The date the item was created - - is_archived : typing.Optional[bool] - Boolean determining if the Item is set to archived - - is_draft : typing.Optional[bool] - Boolean determining if the Item is set to draft - - field_data : typing.Optional[BulkCollectionItemFieldData] + items : typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -488,28 +879,25 @@ def create_item_for_multiple_locales( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) - client.collections.items.create_item_for_multiple_locales( - collection_id="collection_id", - id="580e64008c9a982ac9b8b754", + client.collections.items.delete_items_live( + collection_id="580e63fc8c9a982ac9b8b745", ) """ _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/bulk", - method="POST", + f"collections/{jsonable_encoder(collection_id)}/items/live", + method="DELETE", json={ - "id": id, - "cmsLocaleIds": cms_locale_ids, - "lastPublished": last_published, - "lastUpdated": last_updated, - "createdOn": created_on, - "isArchived": is_archived, - "isDraft": is_draft, - "fieldData": field_data, + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", }, request_options=request_options, omit=OMIT, @@ -518,38 +906,383 @@ def create_item_for_multiple_locales( if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - def get_item( + def update_items_live( self, collection_id: str, - item_id: str, *, - cms_locale_id: typing.Optional[str] = None, + items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CollectionItem: + ) -> CollectionItemListNoPagination: """ - Get details of a selected Collection Item.

Required scope | `CMS:read` + Update a single live item or multiple live items (up to 100) in a Collection + + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + + Required scope | `CMS:write` Parameters ---------- collection_id : str Unique identifier for a Collection - item_id : str - Unique identifier for an Item + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionItemListNoPagination + Request was successful + + Examples + -------- + from webflow import ( + CollectionItemWithIdInput, + CollectionItemWithIdInputFieldData, + Webflow, + ) + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.collections.items.update_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Ne Paniquez Pas", + slug="ne-paniquez-pas", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="No Entrar en Pánico", + slug="no-entrar-en-panico", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Au Revoir et Merci pour Tous les Poissons", + slug="au-revoir-et-merci", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="Hasta Luego y Gracias por Todo el Pescado", + slug="hasta-luego-y-gracias", + ), + ), + ], + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + method="PATCH", + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CollectionItemListNoPagination, + parse_obj_as( + type_=CollectionItemListNoPagination, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def create_items( + self, + collection_id: str, + *, + field_data: CreateBulkCollectionItemRequestBodyFieldData, + cms_locale_ids: typing.Optional[typing.Sequence[str]] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> BulkCollectionItem: + """ + Create an item or multiple items in a CMS Collection across multiple corresponding locales. + + **Notes:** + - This endpoint can create up to 100 items in a request. + - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_data : CreateBulkCollectionItemRequestBodyFieldData + + cms_locale_ids : typing.Optional[typing.Sequence[str]] + Array of identifiers for the locales where the item will be created + + is_archived : typing.Optional[bool] + Indicates whether the item is archived. + + is_draft : typing.Optional[bool] + Indicates whether the item is in draft state. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + BulkCollectionItem + Request was successful + + Examples + -------- + from webflow import Webflow + from webflow.resources.collections.resources.items import SingleCmsItem + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.collections.items.create_items( + collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_ids=[ + "66f6e966c9e1dc700a857ca3", + "66f6e966c9e1dc700a857ca4", + "66f6e966c9e1dc700a857ca5", + ], + is_archived=False, + is_draft=False, + field_data=SingleCmsItem( + name="Don’t Panic", + slug="dont-panic", + ), + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/bulk", + method="POST", + json={ + "cmsLocaleIds": cms_locale_ids, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CreateBulkCollectionItemRequestBodyFieldData, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + BulkCollectionItem, + parse_obj_as( + type_=BulkCollectionItem, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_item( + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CollectionItem: + """ + Get details of a selected Collection Item. + + Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item cms_locale_id : typing.Optional[str] Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. @@ -564,35 +1297,83 @@ def get_item( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.get_item( - collection_id="collection_id", - item_id="item_id", + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", method="GET", - params={"cmsLocaleId": cms_locale_id}, + params={ + "cmsLocaleId": cms_locale_id, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -607,7 +1388,9 @@ def delete_item( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Delete an Item from a Collection. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` + Delete an Item from a Collection. This endpoint does not currently support bulk deletion. + + Required scope | `CMS:write` Parameters ---------- @@ -629,35 +1412,77 @@ def delete_item( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.delete_item( - collection_id="collection_id", - item_id="item_id", + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", method="DELETE", - params={"cmsLocaleId": cms_locale_id}, + params={ + "cmsLocaleId": cms_locale_id, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -668,18 +1493,20 @@ def update_item( collection_id: str, item_id: str, *, - id: str, + id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, last_updated: typing.Optional[str] = OMIT, created_on: typing.Optional[str] = OMIT, is_archived: typing.Optional[bool] = OMIT, is_draft: typing.Optional[bool] = OMIT, - field_data: typing.Optional[CollectionItemFieldData] = OMIT, + field_data: typing.Optional[CollectionItemPatchSingleFieldData] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ - Update a selected Item in a Collection.

Required scope | `CMS:write` + Update a selected Item in a Collection. + + Required scope | `CMS:write` Parameters ---------- @@ -689,7 +1516,7 @@ def update_item( item_id : str Unique identifier for an Item - id : str + id : typing.Optional[str] Unique identifier for the Item cms_locale_id : typing.Optional[str] @@ -710,7 +1537,7 @@ def update_item( is_draft : typing.Optional[bool] Boolean determining if the Item is set to draft - field_data : typing.Optional[CollectionItemFieldData] + field_data : typing.Optional[CollectionItemPatchSingleFieldData] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -722,23 +1549,17 @@ def update_item( Examples -------- - from webflow import CollectionItemFieldData - from webflow.client import Webflow + from webflow import CollectionItemPatchSingleFieldData, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.update_item( - collection_id="collection_id", - item_id="item_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", is_archived=False, is_draft=False, - field_data=CollectionItemFieldData( + field_data=CollectionItemPatchSingleFieldData( name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster", ), @@ -755,24 +1576,72 @@ def update_item( "createdOn": created_on, "isArchived": is_archived, "isDraft": is_draft, - "fieldData": field_data, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" + ), }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -787,7 +1656,9 @@ def get_item_live( request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ - Get details of a selected Collection live Item.

Required scope | `CMS:read` + Get details of a selected Collection live Item. + + Required scope | `CMS:read` Parameters ---------- @@ -810,35 +1681,83 @@ def get_item_live( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.get_item_live( - collection_id="collection_id", - item_id="item_id", + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", method="GET", - params={"cmsLocaleId": cms_locale_id}, + params={ + "cmsLocaleId": cms_locale_id, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -853,7 +1772,11 @@ def delete_item_live( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` + Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. + + This endpoint does not currently support bulk deletion. + + Required scope | `CMS:write` Parameters ---------- @@ -875,35 +1798,77 @@ def delete_item_live( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.delete_item_live( - collection_id="collection_id", - item_id="item_id", + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", method="DELETE", - params={"cmsLocaleId": cms_locale_id}, + params={ + "cmsLocaleId": cms_locale_id, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -914,18 +1879,20 @@ def update_item_live( collection_id: str, item_id: str, *, - id: str, + id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, last_updated: typing.Optional[str] = OMIT, created_on: typing.Optional[str] = OMIT, is_archived: typing.Optional[bool] = OMIT, is_draft: typing.Optional[bool] = OMIT, - field_data: typing.Optional[CollectionItemFieldData] = OMIT, + field_data: typing.Optional[CollectionItemPatchSingleFieldData] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ - Update a selected live Item in a Collection. The updates for this Item will be published to the live site.

Required scope | `CMS:write` + Update a selected live Item in a Collection. The updates for this Item will be published to the live site. + + Required scope | `CMS:write` Parameters ---------- @@ -935,7 +1902,7 @@ def update_item_live( item_id : str Unique identifier for an Item - id : str + id : typing.Optional[str] Unique identifier for the Item cms_locale_id : typing.Optional[str] @@ -956,7 +1923,7 @@ def update_item_live( is_draft : typing.Optional[bool] Boolean determining if the Item is set to draft - field_data : typing.Optional[CollectionItemFieldData] + field_data : typing.Optional[CollectionItemPatchSingleFieldData] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -968,23 +1935,17 @@ def update_item_live( Examples -------- - from webflow import CollectionItemFieldData - from webflow.client import Webflow + from webflow import CollectionItemPatchSingleFieldData, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.update_item_live( - collection_id="collection_id", - item_id="item_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", is_archived=False, is_draft=False, - field_data=CollectionItemFieldData( + field_data=CollectionItemPatchSingleFieldData( name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster", ), @@ -1001,24 +1962,72 @@ def update_item_live( "createdOn": created_on, "isArchived": is_archived, "isDraft": is_draft, - "fieldData": field_data, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" + ), }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1030,9 +2039,11 @@ def publish_item( *, item_ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None, - ) -> None: + ) -> ItemsPublishItemResponse: """ - Publish an item or multiple items.

Required scope | `cms:write` + Publish an item or multiple items. + + Required scope | `cms:write` Parameters ---------- @@ -1046,40 +2057,102 @@ def publish_item( Returns ------- - None + ItemsPublishItemResponse + Request was successful Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.publish_item( - collection_id="collection_id", + collection_id="580e63fc8c9a982ac9b8b745", item_ids=["itemIds"], ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/publish", method="POST", - json={"itemIds": item_ids}, + json={ + "itemIds": item_ids, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return + return typing.cast( + ItemsPublishItemResponse, + parse_obj_as( + type_=ItemsPublishItemResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1104,7 +2177,9 @@ async def list_items( request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemList: """ - List of all Items within a Collection.

Required scope | `CMS:read` + List of all Items within a Collection. + + Required scope | `CMS:read` Parameters ---------- @@ -1142,14 +2217,22 @@ async def list_items( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.list_items( - collection_id="collection_id", - ) + + + async def main() -> None: + await client.collections.items.list_items( + collection_id="580e63fc8c9a982ac9b8b745", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", @@ -1167,17 +2250,63 @@ async def list_items( ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItemList, _response.json()) # type: ignore + return typing.cast( + CollectionItemList, + parse_obj_as( + type_=CollectionItemList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1187,406 +2316,1142 @@ async def create_item( self, collection_id: str, *, - id: str, - cms_locale_id: typing.Optional[str] = OMIT, - last_published: typing.Optional[str] = OMIT, - last_updated: typing.Optional[str] = OMIT, - created_on: typing.Optional[str] = OMIT, - is_archived: typing.Optional[bool] = OMIT, - is_draft: typing.Optional[bool] = OMIT, - field_data: typing.Optional[CollectionItemFieldData] = OMIT, + request: ItemsCreateItemRequest, + request_options: typing.Optional[RequestOptions] = None, + ) -> CollectionItem: + """ + Create Item(s) in a Collection. + + + To create items across multiple locales, please use [this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request : ItemsCreateItemRequest + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionItem + Request was successful + + Examples + -------- + import asyncio + + from webflow import ( + AsyncWebflow, + CollectionItemPostSingle, + CollectionItemPostSingleFieldData, + ) + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.collections.items.create_item( + collection_id="580e63fc8c9a982ac9b8b745", + request=CollectionItemPostSingle( + is_archived=False, + is_draft=False, + field_data=CollectionItemPostSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", + ), + ), + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsCreateItemRequest, direction="write" + ), + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete_items( + self, + collection_id: str, + *, + items: typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Create Item in a Collection.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` + Delete Items from a Collection. + + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be deleted only in the primary locale. + + Required scope | `CMS:write` Parameters ---------- collection_id : str Unique identifier for a Collection - id : str - Unique identifier for the Item + items : typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.collections.items.delete_items( + collection_id="580e63fc8c9a982ac9b8b745", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + method="DELETE", + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[ItemsDeleteItemsRequestItemsItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update_items( + self, + collection_id: str, + *, + items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> CollectionItem: + """ + Update a single item or multiple items (up to 100) in a Collection. + + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionItem + Request was successful + + Examples + -------- + import asyncio + + from webflow import ( + AsyncWebflow, + CollectionItemWithIdInput, + CollectionItemWithIdInputFieldData, + ) + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.collections.items.update_items( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Ne Paniquez Pas", + slug="ne-paniquez-pas", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="No Entrar en Pánico", + slug="no-entrar-en-panico", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Au Revoir et Merci pour Tous les Poissons", + slug="au-revoir-et-merci", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="Hasta Luego y Gracias por Todo el Pescado", + slug="hasta-luego-y-gracias", + ), + ), + ], + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + method="PATCH", + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def list_items_live( + self, + collection_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + name: typing.Optional[str] = None, + slug: typing.Optional[str] = None, + sort_by: typing.Optional[ItemsListItemsLiveRequestSortBy] = None, + sort_order: typing.Optional[ItemsListItemsLiveRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CollectionItemList: + """ + List of all live Items within a Collection. + + Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection cms_locale_id : typing.Optional[str] - Identifier for the locale of the CMS item + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - last_published : typing.Optional[str] - The date the item was last published + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records - last_updated : typing.Optional[str] - The date the item was last updated + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + name : typing.Optional[str] + The name of the item(s) + + slug : typing.Optional[str] + The slug of the item + + sort_by : typing.Optional[ItemsListItemsLiveRequestSortBy] + Sort results by the provided value + + sort_order : typing.Optional[ItemsListItemsLiveRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CollectionItemList + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.collections.items.list_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + "offset": offset, + "limit": limit, + "name": name, + "slug": slug, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CollectionItemList, + parse_obj_as( + type_=CollectionItemList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def create_item_live( + self, + collection_id: str, + *, + request: ItemsCreateItemLiveRequest, + request_options: typing.Optional[RequestOptions] = None, + ) -> CollectionItem: + """ + Create live Item(s) in a Collection. The Item(s) will be published to the live site. + + + To create items across multiple locales, [please use this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) - created_on : typing.Optional[str] - The date the item was created - is_archived : typing.Optional[bool] - Boolean determining if the Item is set to archived + Required scope | `CMS:write` - is_draft : typing.Optional[bool] - Boolean determining if the Item is set to draft + Parameters + ---------- + collection_id : str + Unique identifier for a Collection - field_data : typing.Optional[CollectionItemFieldData] + request : ItemsCreateItemLiveRequest request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - None + CollectionItem + Request was successful Examples -------- - from webflow import CollectionItemFieldData - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow, CollectionItem, CollectionItemFieldData client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.create_item( - collection_id="collection_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), - ) + + + async def main() -> None: + await client.collections.items.create_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + request=CollectionItem( + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", + ), + ), + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items", + f"collections/{jsonable_encoder(collection_id)}/items/live", method="POST", - json={ - "id": id, - "cmsLocaleId": cms_locale_id, - "lastPublished": last_published, - "lastUpdated": last_updated, - "createdOn": created_on, - "isArchived": is_archived, - "isDraft": is_draft, - "fieldData": field_data, - }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsCreateItemLiveRequest, direction="write" + ), request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - async def list_items_live( + async def delete_items_live( self, collection_id: str, *, - cms_locale_id: typing.Optional[str] = None, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, - name: typing.Optional[str] = None, - slug: typing.Optional[str] = None, - sort_by: typing.Optional[ItemsListItemsLiveRequestSortBy] = None, - sort_order: typing.Optional[ItemsListItemsLiveRequestSortOrder] = None, + items: typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CollectionItemList: + ) -> None: """ - List of all live Items within a Collection.

Required scope | `CMS:read` + Remove an item or multiple items (up to 100 items) from the live site. Deleting published items will unpublish the items from the live site and set them to draft. + + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be unpublished only in the primary locale. + + Required scope | `CMS:write` Parameters ---------- collection_id : str Unique identifier for a Collection - cms_locale_id : typing.Optional[str] - Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - - offset : typing.Optional[float] - Offset used for pagination if the results have more than limit records - - limit : typing.Optional[float] - Maximum number of records to be returned (max limit: 100) - - name : typing.Optional[str] - The name of the item(s) - - slug : typing.Optional[str] - The slug of the item - - sort_by : typing.Optional[ItemsListItemsLiveRequestSortBy] - Sort results by the provided value - - sort_order : typing.Optional[ItemsListItemsLiveRequestSortOrder] - Sorts the results by asc or desc + items : typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - CollectionItemList - Request was successful + None Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.list_items_live( - collection_id="collection_id", - ) + + + async def main() -> None: + await client.collections.items.delete_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", - method="GET", - params={ - "cmsLocaleId": cms_locale_id, - "offset": offset, - "limit": limit, - "name": name, - "slug": slug, - "sortBy": sort_by, - "sortOrder": sort_order, + method="DELETE", + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", }, request_options=request_options, + omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItemList, _response.json()) # type: ignore + return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - async def create_item_live( + async def update_items_live( self, collection_id: str, *, - id: str, - cms_locale_id: typing.Optional[str] = OMIT, - last_published: typing.Optional[str] = OMIT, - last_updated: typing.Optional[str] = OMIT, - created_on: typing.Optional[str] = OMIT, - is_archived: typing.Optional[bool] = OMIT, - is_draft: typing.Optional[bool] = OMIT, - field_data: typing.Optional[CollectionItemFieldData] = OMIT, + items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> None: + ) -> CollectionItemListNoPagination: """ - Create live Item in a Collection. This Item will be published to the live site.

To create items across multiple locales, please use this endpoint.

Required scope | `CMS:write` + Update a single live item or multiple live items (up to 100) in a Collection + + **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + + Required scope | `CMS:write` Parameters ---------- collection_id : str Unique identifier for a Collection - id : str - Unique identifier for the Item - - cms_locale_id : typing.Optional[str] - Identifier for the locale of the CMS item - - last_published : typing.Optional[str] - The date the item was last published - - last_updated : typing.Optional[str] - The date the item was last updated - - created_on : typing.Optional[str] - The date the item was created - - is_archived : typing.Optional[bool] - Boolean determining if the Item is set to archived - - is_draft : typing.Optional[bool] - Boolean determining if the Item is set to draft - - field_data : typing.Optional[CollectionItemFieldData] + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - None + CollectionItemListNoPagination + Request was successful Examples -------- - from webflow import CollectionItemFieldData - from webflow.client import AsyncWebflow + import asyncio + + from webflow import ( + AsyncWebflow, + CollectionItemWithIdInput, + CollectionItemWithIdInputFieldData, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.create_item_live( - collection_id="collection_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), - ) + + + async def main() -> None: + await client.collections.items.update_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Ne Paniquez Pas", + slug="ne-paniquez-pas", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="No Entrar en Pánico", + slug="no-entrar-en-panico", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Au Revoir et Merci pour Tous les Poissons", + slug="au-revoir-et-merci", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="Hasta Luego y Gracias por Todo el Pescado", + slug="hasta-luego-y-gracias", + ), + ), + ], + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", - method="POST", + method="PATCH", json={ - "id": id, - "cmsLocaleId": cms_locale_id, - "lastPublished": last_published, - "lastUpdated": last_updated, - "createdOn": created_on, - "isArchived": is_archived, - "isDraft": is_draft, - "fieldData": field_data, + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" + ), + }, + headers={ + "content-type": "application/json", }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return + return typing.cast( + CollectionItemListNoPagination, + parse_obj_as( + type_=CollectionItemListNoPagination, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - async def create_item_for_multiple_locales( + async def create_items( self, collection_id: str, *, - id: str, + field_data: CreateBulkCollectionItemRequestBodyFieldData, cms_locale_ids: typing.Optional[typing.Sequence[str]] = OMIT, - last_published: typing.Optional[str] = OMIT, - last_updated: typing.Optional[str] = OMIT, - created_on: typing.Optional[str] = OMIT, is_archived: typing.Optional[bool] = OMIT, is_draft: typing.Optional[bool] = OMIT, - field_data: typing.Optional[BulkCollectionItemFieldData] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> None: + ) -> BulkCollectionItem: """ - Create single Item in a Collection with multiple corresponding locales.

Required scope | `CMS:write` + Create an item or multiple items in a CMS Collection across multiple corresponding locales. + + **Notes:** + - This endpoint can create up to 100 items in a request. + - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. + + Required scope | `CMS:write` Parameters ---------- collection_id : str Unique identifier for a Collection - id : str - Unique identifier for the Item + field_data : CreateBulkCollectionItemRequestBodyFieldData cms_locale_ids : typing.Optional[typing.Sequence[str]] Array of identifiers for the locales where the item will be created - last_published : typing.Optional[str] - The date the item was last published - - last_updated : typing.Optional[str] - The date the item was last updated - - created_on : typing.Optional[str] - The date the item was created - is_archived : typing.Optional[bool] - Boolean determining if the Item is set to archived + Indicates whether the item is archived. is_draft : typing.Optional[bool] - Boolean determining if the Item is set to draft - - field_data : typing.Optional[BulkCollectionItemFieldData] + Indicates whether the item is in draft state. request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - None + BulkCollectionItem + Request was successful Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow + from webflow.resources.collections.resources.items import SingleCmsItem client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.create_item_for_multiple_locales( - collection_id="collection_id", - id="580e64008c9a982ac9b8b754", - ) + + + async def main() -> None: + await client.collections.items.create_items( + collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_ids=[ + "66f6e966c9e1dc700a857ca3", + "66f6e966c9e1dc700a857ca4", + "66f6e966c9e1dc700a857ca5", + ], + is_archived=False, + is_draft=False, + field_data=SingleCmsItem( + name="Don’t Panic", + slug="dont-panic", + ), + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/bulk", method="POST", json={ - "id": id, "cmsLocaleIds": cms_locale_ids, - "lastPublished": last_published, - "lastUpdated": last_updated, - "createdOn": created_on, "isArchived": is_archived, "isDraft": is_draft, - "fieldData": field_data, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CreateBulkCollectionItemRequestBodyFieldData, direction="write" + ), + }, + headers={ + "content-type": "application/json", }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return + return typing.cast( + BulkCollectionItem, + parse_obj_as( + type_=BulkCollectionItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1601,7 +3466,9 @@ async def get_item( request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ - Get details of a selected Collection Item.

Required scope | `CMS:read` + Get details of a selected Collection Item. + + Required scope | `CMS:read` Parameters ---------- @@ -1624,35 +3491,91 @@ async def get_item( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.get_item( - collection_id="collection_id", - item_id="item_id", - ) + + + async def main() -> None: + await client.collections.items.get_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", method="GET", - params={"cmsLocaleId": cms_locale_id}, + params={ + "cmsLocaleId": cms_locale_id, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1667,7 +3590,9 @@ async def delete_item( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Delete an Item from a Collection. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` + Delete an Item from a Collection. This endpoint does not currently support bulk deletion. + + Required scope | `CMS:write` Parameters ---------- @@ -1689,35 +3614,85 @@ async def delete_item( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.delete_item( - collection_id="collection_id", - item_id="item_id", - ) + + + async def main() -> None: + await client.collections.items.delete_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", method="DELETE", - params={"cmsLocaleId": cms_locale_id}, + params={ + "cmsLocaleId": cms_locale_id, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1728,18 +3703,20 @@ async def update_item( collection_id: str, item_id: str, *, - id: str, + id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, last_updated: typing.Optional[str] = OMIT, created_on: typing.Optional[str] = OMIT, is_archived: typing.Optional[bool] = OMIT, is_draft: typing.Optional[bool] = OMIT, - field_data: typing.Optional[CollectionItemFieldData] = OMIT, + field_data: typing.Optional[CollectionItemPatchSingleFieldData] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ - Update a selected Item in a Collection.

Required scope | `CMS:write` + Update a selected Item in a Collection. + + Required scope | `CMS:write` Parameters ---------- @@ -1749,7 +3726,7 @@ async def update_item( item_id : str Unique identifier for an Item - id : str + id : typing.Optional[str] Unique identifier for the Item cms_locale_id : typing.Optional[str] @@ -1770,7 +3747,7 @@ async def update_item( is_draft : typing.Optional[bool] Boolean determining if the Item is set to draft - field_data : typing.Optional[CollectionItemFieldData] + field_data : typing.Optional[CollectionItemPatchSingleFieldData] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1782,27 +3759,29 @@ async def update_item( Examples -------- - from webflow import CollectionItemFieldData - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow, CollectionItemPatchSingleFieldData client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.update_item( - collection_id="collection_id", - item_id="item_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), - ) + + + async def main() -> None: + await client.collections.items.update_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, + field_data=CollectionItemPatchSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", + ), + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", @@ -1815,24 +3794,72 @@ async def update_item( "createdOn": created_on, "isArchived": is_archived, "isDraft": is_draft, - "fieldData": field_data, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" + ), }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1847,7 +3874,9 @@ async def get_item_live( request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ - Get details of a selected Collection live Item.

Required scope | `CMS:read` + Get details of a selected Collection live Item. + + Required scope | `CMS:read` Parameters ---------- @@ -1870,35 +3899,91 @@ async def get_item_live( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.get_item_live( - collection_id="collection_id", - item_id="item_id", - ) + + + async def main() -> None: + await client.collections.items.get_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", method="GET", - params={"cmsLocaleId": cms_locale_id}, + params={ + "cmsLocaleId": cms_locale_id, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1913,7 +3998,11 @@ async def delete_item_live( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. This endpoint does not currently support bulk deletion.

Required scope | `CMS:write` + Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. + + This endpoint does not currently support bulk deletion. + + Required scope | `CMS:write` Parameters ---------- @@ -1935,35 +4024,85 @@ async def delete_item_live( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.delete_item_live( - collection_id="collection_id", - item_id="item_id", - ) + + + async def main() -> None: + await client.collections.items.delete_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", method="DELETE", - params={"cmsLocaleId": cms_locale_id}, + params={ + "cmsLocaleId": cms_locale_id, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -1974,18 +4113,20 @@ async def update_item_live( collection_id: str, item_id: str, *, - id: str, + id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, last_updated: typing.Optional[str] = OMIT, created_on: typing.Optional[str] = OMIT, is_archived: typing.Optional[bool] = OMIT, is_draft: typing.Optional[bool] = OMIT, - field_data: typing.Optional[CollectionItemFieldData] = OMIT, + field_data: typing.Optional[CollectionItemPatchSingleFieldData] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ - Update a selected live Item in a Collection. The updates for this Item will be published to the live site.

Required scope | `CMS:write` + Update a selected live Item in a Collection. The updates for this Item will be published to the live site. + + Required scope | `CMS:write` Parameters ---------- @@ -1995,7 +4136,7 @@ async def update_item_live( item_id : str Unique identifier for an Item - id : str + id : typing.Optional[str] Unique identifier for the Item cms_locale_id : typing.Optional[str] @@ -2016,7 +4157,7 @@ async def update_item_live( is_draft : typing.Optional[bool] Boolean determining if the Item is set to draft - field_data : typing.Optional[CollectionItemFieldData] + field_data : typing.Optional[CollectionItemPatchSingleFieldData] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -2028,27 +4169,29 @@ async def update_item_live( Examples -------- - from webflow import CollectionItemFieldData - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow, CollectionItemPatchSingleFieldData client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.update_item_live( - collection_id="collection_id", - item_id="item_id", - id="42b720ef280c7a7a3be8cabe", - cms_locale_id="653ad57de882f528b32e810e", - last_published="2022-11-29T16:22:43.159Z", - last_updated="2022-11-17T17:19:43.282Z", - created_on="2022-11-17T17:11:57.148Z", - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), - ) + + + async def main() -> None: + await client.collections.items.update_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, + field_data=CollectionItemPatchSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", + slug="pan-galactic-gargle-blaster", + ), + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", @@ -2061,24 +4204,72 @@ async def update_item_live( "createdOn": created_on, "isArchived": is_archived, "isDraft": is_draft, - "fieldData": field_data, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" + ), }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CollectionItem, _response.json()) # type: ignore + return typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -2090,9 +4281,11 @@ async def publish_item( *, item_ids: typing.Sequence[str], request_options: typing.Optional[RequestOptions] = None, - ) -> None: + ) -> ItemsPublishItemResponse: """ - Publish an item or multiple items.

Required scope | `cms:write` + Publish an item or multiple items. + + Required scope | `cms:write` Parameters ---------- @@ -2106,40 +4299,110 @@ async def publish_item( Returns ------- - None + ItemsPublishItemResponse + Request was successful Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.collections.items.publish_item( - collection_id="collection_id", - item_ids=["itemIds"], - ) + + + async def main() -> None: + await client.collections.items.publish_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_ids=["itemIds"], + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/publish", method="POST", - json={"itemIds": item_ids}, + json={ + "itemIds": item_ids, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return + return typing.cast( + ItemsPublishItemResponse, + parse_obj_as( + type_=ItemsPublishItemResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/collections/resources/items/types/__init__.py b/src/webflow/resources/collections/resources/items/types/__init__.py index fc48f35..67040fb 100644 --- a/src/webflow/resources/collections/resources/items/types/__init__.py +++ b/src/webflow/resources/collections/resources/items/types/__init__.py @@ -1,15 +1,33 @@ # This file was auto-generated by Fern from our API Definition. -from .bulk_collection_item_field_data import BulkCollectionItemFieldData +from .create_bulk_collection_item_request_body_field_data import CreateBulkCollectionItemRequestBodyFieldData +from .create_bulk_collection_item_request_body_field_data_item import CreateBulkCollectionItemRequestBodyFieldDataItem +from .items_create_item_live_request import ItemsCreateItemLiveRequest +from .items_create_item_request import ItemsCreateItemRequest +from .items_delete_items_live_request_items_item import ItemsDeleteItemsLiveRequestItemsItem +from .items_delete_items_request_items_item import ItemsDeleteItemsRequestItemsItem from .items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy from .items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder from .items_list_items_request_sort_by import ItemsListItemsRequestSortBy from .items_list_items_request_sort_order import ItemsListItemsRequestSortOrder +from .items_publish_item_response import ItemsPublishItemResponse +from .multiple_items import MultipleItems +from .multiple_live_items import MultipleLiveItems +from .single_cms_item import SingleCmsItem __all__ = [ - "BulkCollectionItemFieldData", + "CreateBulkCollectionItemRequestBodyFieldData", + "CreateBulkCollectionItemRequestBodyFieldDataItem", + "ItemsCreateItemLiveRequest", + "ItemsCreateItemRequest", + "ItemsDeleteItemsLiveRequestItemsItem", + "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemResponse", + "MultipleItems", + "MultipleLiveItems", + "SingleCmsItem", ] diff --git a/src/webflow/resources/collections/resources/items/types/bulk_collection_item_field_data.py b/src/webflow/resources/collections/resources/items/types/bulk_collection_item_field_data.py deleted file mode 100644 index dadc943..0000000 --- a/src/webflow/resources/collections/resources/items/types/bulk_collection_item_field_data.py +++ /dev/null @@ -1,37 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ......core.datetime_utils import serialize_datetime -from ......core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - - -class BulkCollectionItemFieldData(pydantic_v1.BaseModel): - name: typing.Optional[str] = pydantic_v1.Field(default=None) - """ - Name of the Item - """ - - slug: typing.Optional[str] = pydantic_v1.Field(default=None) - """ - URL structure of the Item in your site. Note: Updates to an item slug will break all links referencing the old slug. - """ - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) - - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data.py b/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data.py new file mode 100644 index 0000000..c4bcb14 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .single_cms_item import SingleCmsItem +from .create_bulk_collection_item_request_body_field_data_item import CreateBulkCollectionItemRequestBodyFieldDataItem + +CreateBulkCollectionItemRequestBodyFieldData = typing.Union[ + SingleCmsItem, typing.List[CreateBulkCollectionItemRequestBodyFieldDataItem] +] diff --git a/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data_item.py b/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data_item.py new file mode 100644 index 0000000..dd6a4f7 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data_item.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import pydantic +from ......core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CreateBulkCollectionItemRequestBodyFieldDataItem(UniversalBaseModel): + """ + A single CMS item to create + """ + + name: str = pydantic.Field() + """ + The name of the item. + """ + + slug: str = pydantic.Field() + """ + URL slug for the item in your site. + Note: Updating the item slug will break all links referencing the old slug. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/items_create_item_live_request.py b/src/webflow/resources/collections/resources/items/types/items_create_item_live_request.py new file mode 100644 index 0000000..dc2f963 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_create_item_live_request.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ......types.collection_item import CollectionItem +from .multiple_live_items import MultipleLiveItems + +ItemsCreateItemLiveRequest = typing.Union[CollectionItem, MultipleLiveItems] diff --git a/src/webflow/resources/collections/resources/items/types/items_create_item_request.py b/src/webflow/resources/collections/resources/items/types/items_create_item_request.py new file mode 100644 index 0000000..7627c55 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_create_item_request.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ......types.collection_item_post_single import CollectionItemPostSingle +from .multiple_items import MultipleItems + +ItemsCreateItemRequest = typing.Union[CollectionItemPostSingle, MultipleItems] diff --git a/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py b/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py new file mode 100644 index 0000000..63e00bc --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ......core.serialization import FieldMetadata +import pydantic +import typing +from ......core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ItemsDeleteItemsLiveRequestItemsItem(UniversalBaseModel): + item_id: typing_extensions.Annotated[str, FieldMetadata(alias="itemId")] = pydantic.Field() + """ + Unique identifier for the Item + """ + + cms_locale_ids: typing_extensions.Annotated[ + typing.Optional[typing.List[str]], FieldMetadata(alias="cmsLocaleIds") + ] = pydantic.Field(default=None) + """ + Array of identifiers for the locales where the item will be created + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/items_delete_items_request_items_item.py b/src/webflow/resources/collections/resources/items/types/items_delete_items_request_items_item.py new file mode 100644 index 0000000..3b66981 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_delete_items_request_items_item.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +import typing +from ......core.serialization import FieldMetadata +from ......core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ItemsDeleteItemsRequestItemsItem(UniversalBaseModel): + id: str = pydantic.Field() + """ + Unique identifier for the Item + """ + + cms_locale_ids: typing_extensions.Annotated[ + typing.Optional[typing.List[str]], FieldMetadata(alias="cmsLocaleIds") + ] = pydantic.Field(default=None) + """ + Array of identifiers for the locales where the item will be created + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_by.py b/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_by.py index f9f5583..9929480 100644 --- a/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_by.py +++ b/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_by.py @@ -1,25 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class ItemsListItemsLiveRequestSortBy(str, enum.Enum): - LAST_PUBLISHED = "lastPublished" - NAME = "name" - SLUG = "slug" - - def visit( - self, - last_published: typing.Callable[[], T_Result], - name: typing.Callable[[], T_Result], - slug: typing.Callable[[], T_Result], - ) -> T_Result: - if self is ItemsListItemsLiveRequestSortBy.LAST_PUBLISHED: - return last_published() - if self is ItemsListItemsLiveRequestSortBy.NAME: - return name() - if self is ItemsListItemsLiveRequestSortBy.SLUG: - return slug() +ItemsListItemsLiveRequestSortBy = typing.Union[typing.Literal["lastPublished", "name", "slug"], typing.Any] diff --git a/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_order.py b/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_order.py index 6ce16f4..5666223 100644 --- a/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_order.py +++ b/src/webflow/resources/collections/resources/items/types/items_list_items_live_request_sort_order.py @@ -1,17 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class ItemsListItemsLiveRequestSortOrder(str, enum.Enum): - ASC = "asc" - DESC = "desc" - - def visit(self, asc: typing.Callable[[], T_Result], desc: typing.Callable[[], T_Result]) -> T_Result: - if self is ItemsListItemsLiveRequestSortOrder.ASC: - return asc() - if self is ItemsListItemsLiveRequestSortOrder.DESC: - return desc() +ItemsListItemsLiveRequestSortOrder = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_by.py b/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_by.py index 459f68f..222d1ff 100644 --- a/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_by.py +++ b/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_by.py @@ -1,25 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class ItemsListItemsRequestSortBy(str, enum.Enum): - LAST_PUBLISHED = "lastPublished" - NAME = "name" - SLUG = "slug" - - def visit( - self, - last_published: typing.Callable[[], T_Result], - name: typing.Callable[[], T_Result], - slug: typing.Callable[[], T_Result], - ) -> T_Result: - if self is ItemsListItemsRequestSortBy.LAST_PUBLISHED: - return last_published() - if self is ItemsListItemsRequestSortBy.NAME: - return name() - if self is ItemsListItemsRequestSortBy.SLUG: - return slug() +ItemsListItemsRequestSortBy = typing.Union[typing.Literal["lastPublished", "name", "slug"], typing.Any] diff --git a/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_order.py b/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_order.py index a27080d..887dfcc 100644 --- a/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_order.py +++ b/src/webflow/resources/collections/resources/items/types/items_list_items_request_sort_order.py @@ -1,17 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class ItemsListItemsRequestSortOrder(str, enum.Enum): - ASC = "asc" - DESC = "desc" - - def visit(self, asc: typing.Callable[[], T_Result], desc: typing.Callable[[], T_Result]) -> T_Result: - if self is ItemsListItemsRequestSortOrder.ASC: - return asc() - if self is ItemsListItemsRequestSortOrder.DESC: - return desc() +ItemsListItemsRequestSortOrder = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/webflow/resources/collections/resources/items/types/items_publish_item_response.py b/src/webflow/resources/collections/resources/items/types/items_publish_item_response.py new file mode 100644 index 0000000..f793223 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_publish_item_response.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ......core.serialization import FieldMetadata +from ......core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ItemsPublishItemResponse(UniversalBaseModel): + published_item_ids: typing_extensions.Annotated[ + typing.Optional[typing.List[str]], FieldMetadata(alias="publishedItemIds") + ] = None + errors: typing.Optional[typing.List[str]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/multiple_items.py b/src/webflow/resources/collections/resources/items/types/multiple_items.py new file mode 100644 index 0000000..8700990 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/multiple_items.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import typing +from ......types.collection_item_post_single import CollectionItemPostSingle +import pydantic +from ......core.pydantic_utilities import IS_PYDANTIC_V2 + + +class MultipleItems(UniversalBaseModel): + items: typing.Optional[typing.List[CollectionItemPostSingle]] = pydantic.Field(default=None) + """ + An array of items to create + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/multiple_live_items.py b/src/webflow/resources/collections/resources/items/types/multiple_live_items.py new file mode 100644 index 0000000..156fecf --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/multiple_live_items.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import typing +from ......types.collection_item import CollectionItem +import pydantic +from ......core.pydantic_utilities import IS_PYDANTIC_V2 + + +class MultipleLiveItems(UniversalBaseModel): + items: typing.Optional[typing.List[CollectionItem]] = pydantic.Field(default=None) + """ + List of collection items to create + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/single_cms_item.py b/src/webflow/resources/collections/resources/items/types/single_cms_item.py new file mode 100644 index 0000000..b64f1a4 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/single_cms_item.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import pydantic +from ......core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class SingleCmsItem(UniversalBaseModel): + name: str = pydantic.Field() + """ + The name of the item. + """ + + slug: str = pydantic.Field() + """ + URL slug for the item in your site. + Note: Updating the item slug will break all links referencing the old slug. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/components/__init__.py b/src/webflow/resources/components/__init__.py new file mode 100644 index 0000000..36f01b7 --- /dev/null +++ b/src/webflow/resources/components/__init__.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import ( + ComponentDomWriteNodesItem, + ComponentPropertiesWritePropertiesItem, + ComponentsUpdateContentResponse, + ComponentsUpdatePropertiesResponse, +) + +__all__ = [ + "ComponentDomWriteNodesItem", + "ComponentPropertiesWritePropertiesItem", + "ComponentsUpdateContentResponse", + "ComponentsUpdatePropertiesResponse", +] diff --git a/src/webflow/resources/components/client.py b/src/webflow/resources/components/client.py new file mode 100644 index 0000000..ef50ac9 --- /dev/null +++ b/src/webflow/resources/components/client.py @@ -0,0 +1,1476 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ...core.client_wrapper import SyncClientWrapper +from ...core.request_options import RequestOptions +from ...types.component_list import ComponentList +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as +from ...errors.bad_request_error import BadRequestError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError +from ...types.component_dom import ComponentDom +from .types.component_dom_write_nodes_item import ComponentDomWriteNodesItem +from .types.components_update_content_response import ComponentsUpdateContentResponse +from ...core.serialization import convert_and_respect_annotation_metadata +from ...errors.forbidden_error import ForbiddenError +from ...types.component_properties import ComponentProperties +from .types.component_properties_write_properties_item import ComponentPropertiesWritePropertiesItem +from .types.components_update_properties_response import ComponentsUpdatePropertiesResponse +from ...core.client_wrapper import AsyncClientWrapper + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class ComponentsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + site_id: str, + *, + limit: typing.Optional[float] = None, + offset: typing.Optional[float] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ComponentList: + """ + List of all components for a site. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ComponentList + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.components.list( + site_id="580e63e98c9a982ac9b8b741", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components", + method="GET", + params={ + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ComponentList, + parse_obj_as( + type_=ComponentList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_content( + self, + site_id: str, + component_id: str, + *, + locale_id: typing.Optional[str] = None, + limit: typing.Optional[float] = None, + offset: typing.Optional[float] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ComponentDom: + """ + Get static content from a component definition. This includes text nodes, image nodes and nested component instances. + To retrieve dynamic content set by component properties, use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + + If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ComponentDom + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.components.get_content( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + method="GET", + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ComponentDom, + parse_obj_as( + type_=ComponentDom, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update_content( + self, + site_id: str, + component_id: str, + *, + nodes: typing.Sequence[ComponentDomWriteNodesItem], + locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ComponentsUpdateContentResponse: + """ + This endpoint updates content within a component defintion for **secondary locales**. It supports updating up to 1000 nodes in a single request. + + Before making updates: + 1. Use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint to identify available content nodes and their types + 2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint + + + This endpoint is specifically for localizing component definitions. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + + Required scope | `components:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + nodes : typing.Sequence[ComponentDomWriteNodesItem] + List of DOM Nodes with the new content that will be updated in each node. + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ComponentsUpdateContentResponse + Request was successful + + Examples + -------- + from webflow import ( + ComponentInstanceNodePropertyOverridesWrite, + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + TextNodeWrite, + Webflow, + ) + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.components.update_content( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + nodes=[ + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", + text="

The Hitchhiker's Guide to the Galaxy

", + ), + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + ComponentInstanceNodePropertyOverridesWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + property_overrides=[ + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", + text="

Time is an illusion

", + ), + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", + text="Life, the Universe and Everything", + ), + ], + ), + ], + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + method="POST", + params={ + "localeId": locale_id, + }, + json={ + "nodes": convert_and_respect_annotation_metadata( + object_=nodes, annotation=typing.Sequence[ComponentDomWriteNodesItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ComponentsUpdateContentResponse, + parse_obj_as( + type_=ComponentsUpdateContentResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_properties( + self, + site_id: str, + component_id: str, + *, + locale_id: typing.Optional[str] = None, + limit: typing.Optional[float] = None, + offset: typing.Optional[float] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ComponentProperties: + """ + Get the property default values of a component definition. + + If you do not provide a Locale ID in your request, the response will return any properties that can be localized from the Primary locale. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ComponentProperties + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.components.get_properties( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + method="GET", + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ComponentProperties, + parse_obj_as( + type_=ComponentProperties, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update_properties( + self, + site_id: str, + component_id: str, + *, + properties: typing.Sequence[ComponentPropertiesWritePropertiesItem], + locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ComponentsUpdatePropertiesResponse: + """ + Update the property default values of a component definition in a specificed locale. + + Before making updates: + 1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify available properties + + The request requires a secondary locale ID. If a locale is missing, the request will not be processed and will result in an error. + + Required scope | `components:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + properties : typing.Sequence[ComponentPropertiesWritePropertiesItem] + A list of component properties to update within the specified secondary locale. + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ComponentsUpdatePropertiesResponse + Request was successful + + Examples + -------- + from webflow import Webflow + from webflow.resources.components import ComponentPropertiesWritePropertiesItem + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.components.update_properties( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + properties=[ + ComponentPropertiesWritePropertiesItem( + property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", + text="The Hitchhiker’s Guide to the Galaxy", + ), + ComponentPropertiesWritePropertiesItem( + property_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Dont Panic!

Always know where your towel is.

", + ), + ], + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + method="POST", + params={ + "localeId": locale_id, + }, + json={ + "properties": convert_and_respect_annotation_metadata( + object_=properties, + annotation=typing.Sequence[ComponentPropertiesWritePropertiesItem], + direction="write", + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ComponentsUpdatePropertiesResponse, + parse_obj_as( + type_=ComponentsUpdatePropertiesResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncComponentsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + site_id: str, + *, + limit: typing.Optional[float] = None, + offset: typing.Optional[float] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ComponentList: + """ + List of all components for a site. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ComponentList + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.components.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components", + method="GET", + params={ + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ComponentList, + parse_obj_as( + type_=ComponentList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_content( + self, + site_id: str, + component_id: str, + *, + locale_id: typing.Optional[str] = None, + limit: typing.Optional[float] = None, + offset: typing.Optional[float] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ComponentDom: + """ + Get static content from a component definition. This includes text nodes, image nodes and nested component instances. + To retrieve dynamic content set by component properties, use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + + If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ComponentDom + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.components.get_content( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + method="GET", + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ComponentDom, + parse_obj_as( + type_=ComponentDom, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update_content( + self, + site_id: str, + component_id: str, + *, + nodes: typing.Sequence[ComponentDomWriteNodesItem], + locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ComponentsUpdateContentResponse: + """ + This endpoint updates content within a component defintion for **secondary locales**. It supports updating up to 1000 nodes in a single request. + + Before making updates: + 1. Use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint to identify available content nodes and their types + 2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint + + + This endpoint is specifically for localizing component definitions. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + + Required scope | `components:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + nodes : typing.Sequence[ComponentDomWriteNodesItem] + List of DOM Nodes with the new content that will be updated in each node. + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ComponentsUpdateContentResponse + Request was successful + + Examples + -------- + import asyncio + + from webflow import ( + AsyncWebflow, + ComponentInstanceNodePropertyOverridesWrite, + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + TextNodeWrite, + ) + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.components.update_content( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + nodes=[ + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", + text="

The Hitchhiker's Guide to the Galaxy

", + ), + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + ComponentInstanceNodePropertyOverridesWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + property_overrides=[ + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", + text="

Time is an illusion

", + ), + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", + text="Life, the Universe and Everything", + ), + ], + ), + ], + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + method="POST", + params={ + "localeId": locale_id, + }, + json={ + "nodes": convert_and_respect_annotation_metadata( + object_=nodes, annotation=typing.Sequence[ComponentDomWriteNodesItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ComponentsUpdateContentResponse, + parse_obj_as( + type_=ComponentsUpdateContentResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_properties( + self, + site_id: str, + component_id: str, + *, + locale_id: typing.Optional[str] = None, + limit: typing.Optional[float] = None, + offset: typing.Optional[float] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ComponentProperties: + """ + Get the property default values of a component definition. + + If you do not provide a Locale ID in your request, the response will return any properties that can be localized from the Primary locale. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ComponentProperties + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.components.get_properties( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + method="GET", + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ComponentProperties, + parse_obj_as( + type_=ComponentProperties, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update_properties( + self, + site_id: str, + component_id: str, + *, + properties: typing.Sequence[ComponentPropertiesWritePropertiesItem], + locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ComponentsUpdatePropertiesResponse: + """ + Update the property default values of a component definition in a specificed locale. + + Before making updates: + 1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify available properties + + The request requires a secondary locale ID. If a locale is missing, the request will not be processed and will result in an error. + + Required scope | `components:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + properties : typing.Sequence[ComponentPropertiesWritePropertiesItem] + A list of component properties to update within the specified secondary locale. + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ComponentsUpdatePropertiesResponse + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + from webflow.resources.components import ComponentPropertiesWritePropertiesItem + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.components.update_properties( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + properties=[ + ComponentPropertiesWritePropertiesItem( + property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", + text="The Hitchhiker’s Guide to the Galaxy", + ), + ComponentPropertiesWritePropertiesItem( + property_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Dont Panic!

Always know where your towel is.

", + ), + ], + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + method="POST", + params={ + "localeId": locale_id, + }, + json={ + "properties": convert_and_respect_annotation_metadata( + object_=properties, + annotation=typing.Sequence[ComponentPropertiesWritePropertiesItem], + direction="write", + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + ComponentsUpdatePropertiesResponse, + parse_obj_as( + type_=ComponentsUpdatePropertiesResponse, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/webflow/resources/components/types/__init__.py b/src/webflow/resources/components/types/__init__.py new file mode 100644 index 0000000..dc8d684 --- /dev/null +++ b/src/webflow/resources/components/types/__init__.py @@ -0,0 +1,13 @@ +# This file was auto-generated by Fern from our API Definition. + +from .component_dom_write_nodes_item import ComponentDomWriteNodesItem +from .component_properties_write_properties_item import ComponentPropertiesWritePropertiesItem +from .components_update_content_response import ComponentsUpdateContentResponse +from .components_update_properties_response import ComponentsUpdatePropertiesResponse + +__all__ = [ + "ComponentDomWriteNodesItem", + "ComponentPropertiesWritePropertiesItem", + "ComponentsUpdateContentResponse", + "ComponentsUpdatePropertiesResponse", +] diff --git a/src/webflow/resources/components/types/component_dom_write_nodes_item.py b/src/webflow/resources/components/types/component_dom_write_nodes_item.py new file mode 100644 index 0000000..27888e6 --- /dev/null +++ b/src/webflow/resources/components/types/component_dom_write_nodes_item.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ....types.text_node_write import TextNodeWrite +from ....types.component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite + +ComponentDomWriteNodesItem = typing.Union[TextNodeWrite, ComponentInstanceNodePropertyOverridesWrite] diff --git a/src/webflow/resources/components/types/component_properties_write_properties_item.py b/src/webflow/resources/components/types/component_properties_write_properties_item.py new file mode 100644 index 0000000..b4f8f50 --- /dev/null +++ b/src/webflow/resources/components/types/component_properties_write_properties_item.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ....core.serialization import FieldMetadata +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class ComponentPropertiesWritePropertiesItem(UniversalBaseModel): + property_id: typing_extensions.Annotated[str, FieldMetadata(alias="propertyId")] = pydantic.Field() + """ + The ID of the property. + """ + + text: str = pydantic.Field() + """ + The new string or HTML value used to update the component property in the secondary locale. + + The provided value must be compatible with the type of the component property. + + For example, attempting to update a single-line plain-text property with a multi-line + value will result in an error. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/components/types/components_update_content_response.py b/src/webflow/resources/components/types/components_update_content_response.py new file mode 100644 index 0000000..6129dda --- /dev/null +++ b/src/webflow/resources/components/types/components_update_content_response.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ComponentsUpdateContentResponse(UniversalBaseModel): + errors: typing.List[str] = pydantic.Field() + """ + A list of error messages, if any. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/components/types/components_update_properties_response.py b/src/webflow/resources/components/types/components_update_properties_response.py new file mode 100644 index 0000000..b0c8824 --- /dev/null +++ b/src/webflow/resources/components/types/components_update_properties_response.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ComponentsUpdatePropertiesResponse(UniversalBaseModel): + errors: typing.List[str] = pydantic.Field() + """ + A list of error messages, if any. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/ecommerce/client.py b/src/webflow/resources/ecommerce/client.py index 3baa775..bbd3a5d 100644 --- a/src/webflow/resources/ecommerce/client.py +++ b/src/webflow/resources/ecommerce/client.py @@ -1,21 +1,22 @@ # This file was auto-generated by Fern from our API Definition. +from ...core.client_wrapper import SyncClientWrapper import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions +from ...types.ecommerce_settings import EcommerceSettings +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError -from ...errors.conflict_error import ConflictError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.forbidden_error import ForbiddenError -from ...errors.internal_server_error import InternalServerError from ...errors.not_found_error import NotFoundError +from ...errors.conflict_error import ConflictError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.ecommerce_settings import EcommerceSettings +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper class EcommerceClient: @@ -45,35 +46,99 @@ def get_settings( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.ecommerce.get_settings( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(EcommerceSettings, _response.json()) # type: ignore + return typing.cast( + EcommerceSettings, + parse_obj_as( + type_=EcommerceSettings, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -107,35 +172,107 @@ async def get_settings( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.ecommerce.get_settings( - site_id="site_id", - ) + + + async def main() -> None: + await client.ecommerce.get_settings( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(EcommerceSettings, _response.json()) # type: ignore + return typing.cast( + EcommerceSettings, + parse_obj_as( + type_=EcommerceSettings, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/forms/client.py b/src/webflow/resources/forms/client.py index d5a86a0..515b631 100644 --- a/src/webflow/resources/forms/client.py +++ b/src/webflow/resources/forms/client.py @@ -1,24 +1,25 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from ...core.client_wrapper import SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.form_list import FormList +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError -from ...errors.conflict_error import ConflictError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.forbidden_error import ForbiddenError -from ...errors.internal_server_error import InternalServerError from ...errors.not_found_error import NotFoundError +from ...errors.conflict_error import ConflictError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError from ...types.form import Form -from ...types.form_list import FormList -from ...types.form_submission import FormSubmission from ...types.form_submission_list import FormSubmissionList +from ...types.form_submission import FormSubmission +from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -37,7 +38,9 @@ def list( request_options: typing.Optional[RequestOptions] = None, ) -> FormList: """ - List forms for a given site

Required scope | `forms:read` + List forms for a given site. + + Required scope | `forms:read` Parameters ---------- @@ -60,38 +63,103 @@ def list( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.forms.list( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/forms", method="GET", - params={"limit": limit, "offset": offset}, + params={ + "limit": limit, + "offset": offset, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(FormList, _response.json()) # type: ignore + return typing.cast( + FormList, + parse_obj_as( + type_=FormList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -99,7 +167,9 @@ def list( def get(self, form_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Form: """ - Get information about a given form

Required scope | `forms:read` + Get information about a given form. + + Required scope | `forms:read` Parameters ---------- @@ -116,49 +186,118 @@ def get(self, form_id: str, *, request_options: typing.Optional[RequestOptions] Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.forms.get( - form_id="form_id", + form_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"forms/{jsonable_encoder(form_id)}", method="GET", request_options=request_options + f"forms/{jsonable_encoder(form_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Form, _response.json()) # type: ignore + return typing.cast( + Form, + parse_obj_as( + type_=Form, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) def list_submissions( - self, form_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, + form_id: str, + *, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + request_options: typing.Optional[RequestOptions] = None, ) -> FormSubmissionList: """ - List form submissions for a given form

Required scope | `forms:read` + List form submissions for a given form + + Required scope | `forms:read` Parameters ---------- form_id : str Unique identifier for a Form + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -169,33 +308,93 @@ def list_submissions( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.forms.list_submissions( - form_id="form_id", + form_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"forms/{jsonable_encoder(form_id)}/submissions", method="GET", request_options=request_options + f"forms/{jsonable_encoder(form_id)}/submissions", + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(FormSubmissionList, _response.json()) # type: ignore + return typing.cast( + FormSubmissionList, + parse_obj_as( + type_=FormSubmissionList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -205,7 +404,9 @@ def get_submission( self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> FormSubmission: """ - Get information about a given form submission

Required scope | `forms:read` + Get information about a given form submissio. + + Required scope | `forms:read` Parameters ---------- @@ -222,33 +423,89 @@ def get_submission( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.forms.get_submission( - form_submission_id="form_submission_id", + form_submission_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"form_submissions/{jsonable_encoder(form_submission_id)}", method="GET", request_options=request_options + f"form_submissions/{jsonable_encoder(form_submission_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(FormSubmission, _response.json()) # type: ignore + return typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -258,18 +515,20 @@ def update_submission( self, form_submission_id: str, *, - form_submission_data: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + form_submission_data: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> FormSubmission: """ - Update hidden fields on a form submission

Required scope | `forms:write` + Update hidden fields on a form submission + + Required scope | `forms:write` Parameters ---------- form_submission_id : str Unique identifier for a Form Submission - form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] + form_submission_data : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] An existing **hidden field** defined on the form schema, and the corresponding value to set request_options : typing.Optional[RequestOptions] @@ -282,39 +541,106 @@ def update_submission( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.forms.update_submission( - form_submission_id="form_submission_id", + form_submission_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( f"form_submissions/{jsonable_encoder(form_submission_id)}", method="PATCH", - json={"formSubmissionData": form_submission_data}, + json={ + "formSubmissionData": form_submission_data, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(FormSubmission, _response.json()) # type: ignore + return typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -334,7 +660,9 @@ async def list( request_options: typing.Optional[RequestOptions] = None, ) -> FormList: """ - List forms for a given site

Required scope | `forms:read` + List forms for a given site. + + Required scope | `forms:read` Parameters ---------- @@ -357,38 +685,111 @@ async def list( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.forms.list( - site_id="site_id", - ) + + + async def main() -> None: + await client.forms.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/forms", method="GET", - params={"limit": limit, "offset": offset}, + params={ + "limit": limit, + "offset": offset, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(FormList, _response.json()) # type: ignore + return typing.cast( + FormList, + parse_obj_as( + type_=FormList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -396,7 +797,9 @@ async def list( async def get(self, form_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Form: """ - Get information about a given form

Required scope | `forms:read` + Get information about a given form. + + Required scope | `forms:read` Parameters ---------- @@ -413,49 +816,126 @@ async def get(self, form_id: str, *, request_options: typing.Optional[RequestOpt Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.forms.get( - form_id="form_id", - ) + + + async def main() -> None: + await client.forms.get( + form_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"forms/{jsonable_encoder(form_id)}", method="GET", request_options=request_options + f"forms/{jsonable_encoder(form_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Form, _response.json()) # type: ignore + return typing.cast( + Form, + parse_obj_as( + type_=Form, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) async def list_submissions( - self, form_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, + form_id: str, + *, + offset: typing.Optional[float] = None, + limit: typing.Optional[float] = None, + request_options: typing.Optional[RequestOptions] = None, ) -> FormSubmissionList: """ - List form submissions for a given form

Required scope | `forms:read` + List form submissions for a given form + + Required scope | `forms:read` Parameters ---------- form_id : str Unique identifier for a Form + offset : typing.Optional[float] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[float] + Maximum number of records to be returned (max limit: 100) + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -466,33 +946,101 @@ async def list_submissions( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.forms.list_submissions( - form_id="form_id", - ) + + + async def main() -> None: + await client.forms.list_submissions( + form_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"forms/{jsonable_encoder(form_id)}/submissions", method="GET", request_options=request_options + f"forms/{jsonable_encoder(form_id)}/submissions", + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(FormSubmissionList, _response.json()) # type: ignore + return typing.cast( + FormSubmissionList, + parse_obj_as( + type_=FormSubmissionList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -502,7 +1050,9 @@ async def get_submission( self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> FormSubmission: """ - Get information about a given form submission

Required scope | `forms:read` + Get information about a given form submissio. + + Required scope | `forms:read` Parameters ---------- @@ -519,33 +1069,97 @@ async def get_submission( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.forms.get_submission( - form_submission_id="form_submission_id", - ) + + + async def main() -> None: + await client.forms.get_submission( + form_submission_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"form_submissions/{jsonable_encoder(form_submission_id)}", method="GET", request_options=request_options + f"form_submissions/{jsonable_encoder(form_submission_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(FormSubmission, _response.json()) # type: ignore + return typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -555,18 +1169,20 @@ async def update_submission( self, form_submission_id: str, *, - form_submission_data: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + form_submission_data: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> FormSubmission: """ - Update hidden fields on a form submission

Required scope | `forms:write` + Update hidden fields on a form submission + + Required scope | `forms:write` Parameters ---------- form_submission_id : str Unique identifier for a Form Submission - form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] + form_submission_data : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] An existing **hidden field** defined on the form schema, and the corresponding value to set request_options : typing.Optional[RequestOptions] @@ -579,39 +1195,114 @@ async def update_submission( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.forms.update_submission( - form_submission_id="form_submission_id", - ) + + + async def main() -> None: + await client.forms.update_submission( + form_submission_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"form_submissions/{jsonable_encoder(form_submission_id)}", method="PATCH", - json={"formSubmissionData": form_submission_data}, + json={ + "formSubmissionData": form_submission_data, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(FormSubmission, _response.json()) # type: ignore + return typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/inventory/client.py b/src/webflow/resources/inventory/client.py index 44e16ea..27e4f3c 100644 --- a/src/webflow/resources/inventory/client.py +++ b/src/webflow/resources/inventory/client.py @@ -1,22 +1,23 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from ...core.client_wrapper import SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.inventory_item import InventoryItem +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError -from ...errors.conflict_error import ConflictError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.forbidden_error import ForbiddenError -from ...errors.internal_server_error import InternalServerError from ...errors.not_found_error import NotFoundError +from ...errors.conflict_error import ConflictError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.inventory_item import InventoryItem +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError from .types.inventory_update_request_inventory_type import InventoryUpdateRequestInventoryType +from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -52,14 +53,14 @@ def list( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.inventory.list( - collection_id="collection_id", - item_id="item_id", + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", ) """ _response = self._client_wrapper.httpx_client.request( @@ -69,21 +70,83 @@ def list( ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(InventoryItem, _response.json()) # type: ignore + return typing.cast( + InventoryItem, + parse_obj_as( + type_=InventoryItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -100,7 +163,11 @@ def update( request_options: typing.Optional[RequestOptions] = None, ) -> InventoryItem: """ - Updates the current inventory levels for a particular SKU item. Updates may be given in one or two methods, absolutely or incrementally. Absolute updates are done by setting `quantity` directly. Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. + Updates the current inventory levels for a particular SKU item. + + Updates may be given in one or two methods, absolutely or incrementally. + - Absolute updates are done by setting `quantity` directly. + - Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. Required scope | `ecommerce:write` @@ -131,42 +198,110 @@ def update( Examples -------- - from webflow import InventoryUpdateRequestInventoryType - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.inventory.update( - collection_id="collection_id", - item_id="item_id", - inventory_type=InventoryUpdateRequestInventoryType.INFINITE, + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + inventory_type="infinite", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", method="PATCH", - json={"inventoryType": inventory_type, "updateQuantity": update_quantity, "quantity": quantity}, + json={ + "inventoryType": inventory_type, + "updateQuantity": update_quantity, + "quantity": quantity, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(InventoryItem, _response.json()) # type: ignore + return typing.cast( + InventoryItem, + parse_obj_as( + type_=InventoryItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -203,15 +338,23 @@ async def list( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.inventory.list( - collection_id="collection_id", - item_id="item_id", - ) + + + async def main() -> None: + await client.inventory.list( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", @@ -220,21 +363,83 @@ async def list( ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(InventoryItem, _response.json()) # type: ignore + return typing.cast( + InventoryItem, + parse_obj_as( + type_=InventoryItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -251,7 +456,11 @@ async def update( request_options: typing.Optional[RequestOptions] = None, ) -> InventoryItem: """ - Updates the current inventory levels for a particular SKU item. Updates may be given in one or two methods, absolutely or incrementally. Absolute updates are done by setting `quantity` directly. Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. + Updates the current inventory levels for a particular SKU item. + + Updates may be given in one or two methods, absolutely or incrementally. + - Absolute updates are done by setting `quantity` directly. + - Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. Required scope | `ecommerce:write` @@ -282,42 +491,118 @@ async def update( Examples -------- - from webflow import InventoryUpdateRequestInventoryType - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.inventory.update( - collection_id="collection_id", - item_id="item_id", - inventory_type=InventoryUpdateRequestInventoryType.INFINITE, - ) + + + async def main() -> None: + await client.inventory.update( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + inventory_type="infinite", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", method="PATCH", - json={"inventoryType": inventory_type, "updateQuantity": update_quantity, "quantity": quantity}, + json={ + "inventoryType": inventory_type, + "updateQuantity": update_quantity, + "quantity": quantity, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(InventoryItem, _response.json()) # type: ignore + return typing.cast( + InventoryItem, + parse_obj_as( + type_=InventoryItem, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/inventory/types/inventory_update_request_inventory_type.py b/src/webflow/resources/inventory/types/inventory_update_request_inventory_type.py index f4d4643..90479e3 100644 --- a/src/webflow/resources/inventory/types/inventory_update_request_inventory_type.py +++ b/src/webflow/resources/inventory/types/inventory_update_request_inventory_type.py @@ -1,21 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class InventoryUpdateRequestInventoryType(str, enum.Enum): - """ - infinite or finite - """ - - INFINITE = "infinite" - FINITE = "finite" - - def visit(self, infinite: typing.Callable[[], T_Result], finite: typing.Callable[[], T_Result]) -> T_Result: - if self is InventoryUpdateRequestInventoryType.INFINITE: - return infinite() - if self is InventoryUpdateRequestInventoryType.FINITE: - return finite() +InventoryUpdateRequestInventoryType = typing.Union[typing.Literal["infinite", "finite"], typing.Any] diff --git a/src/webflow/resources/orders/client.py b/src/webflow/resources/orders/client.py index 21dc5e8..4aa4b77 100644 --- a/src/webflow/resources/orders/client.py +++ b/src/webflow/resources/orders/client.py @@ -1,24 +1,25 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from ...core.client_wrapper import SyncClientWrapper +from .types.orders_list_request_status import OrdersListRequestStatus from ...core.request_options import RequestOptions +from ...types.order_list import OrderList +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError -from ...errors.conflict_error import ConflictError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.forbidden_error import ForbiddenError -from ...errors.internal_server_error import InternalServerError from ...errors.not_found_error import NotFoundError +from ...errors.conflict_error import ConflictError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError from ...types.order import Order -from ...types.order_list import OrderList -from .types.orders_list_request_status import OrdersListRequestStatus from .types.orders_refund_request_reason import OrdersRefundRequestReason +from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -66,38 +67,104 @@ def list( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.orders.list( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders", method="GET", - params={"status": status, "offset": offset, "limit": limit}, + params={ + "status": status, + "offset": offset, + "limit": limit, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(OrderList, _response.json()) # type: ignore + return typing.cast( + OrderList, + parse_obj_as( + type_=OrderList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -105,7 +172,8 @@ def list( def get(self, site_id: str, order_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Order: """ - Retrieve a single product by its id. All of its SKUs will also be retrieved. + Retrieve a single product by its ID. All of its SKUs will also be + retrieved. Required scope | `ecommerce:read` @@ -127,14 +195,14 @@ def get(self, site_id: str, order_id: str, *, request_options: typing.Optional[R Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.orders.get( - site_id="site_id", - order_id="order_id", + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) """ _response = self._client_wrapper.httpx_client.request( @@ -144,21 +212,83 @@ def get(self, site_id: str, order_id: str, *, request_options: typing.Optional[R ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + return typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -176,7 +306,9 @@ def update( request_options: typing.Optional[RequestOptions] = None, ) -> Order: """ - This API lets you update the fields, `comment`, `shippingProvider`, and/or `shippingTracking` for a given order. All three fields can be updated simultaneously or independently. + This API lets you update the fields, `comment`, `shippingProvider`, + and/or `shippingTracking` for a given order. All three fields can be + updated simultaneously or independently. Required scope | `ecommerce:write` @@ -210,14 +342,14 @@ def update( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.orders.update( - site_id="site_id", - order_id="order_id", + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) """ _response = self._client_wrapper.httpx_client.request( @@ -229,26 +361,91 @@ def update( "shippingTracking": shipping_tracking, "shippingTrackingURL": shipping_tracking_url, }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + return typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -288,40 +485,107 @@ def update_fulfill( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.orders.update_fulfill( - site_id="site_id", - order_id="order_id", + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", method="POST", - json={"sendOrderFulfilledEmail": send_order_fulfilled_email}, + json={ + "sendOrderFulfilledEmail": send_order_fulfilled_email, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + return typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -353,14 +617,14 @@ def update_unfulfill( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.orders.update_unfulfill( - site_id="site_id", - order_id="order_id", + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) """ _response = self._client_wrapper.httpx_client.request( @@ -370,21 +634,83 @@ def update_unfulfill( ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + return typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -425,40 +751,107 @@ def refund( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.orders.refund( - site_id="site_id", - order_id="order_id", + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", method="POST", - json={"reason": reason}, + json={ + "reason": reason, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + return typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -507,38 +900,112 @@ async def list( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.orders.list( - site_id="site_id", - ) + + + async def main() -> None: + await client.orders.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders", method="GET", - params={"status": status, "offset": offset, "limit": limit}, + params={ + "status": status, + "offset": offset, + "limit": limit, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(OrderList, _response.json()) # type: ignore + return typing.cast( + OrderList, + parse_obj_as( + type_=OrderList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -548,7 +1015,8 @@ async def get( self, site_id: str, order_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> Order: """ - Retrieve a single product by its id. All of its SKUs will also be retrieved. + Retrieve a single product by its ID. All of its SKUs will also be + retrieved. Required scope | `ecommerce:read` @@ -570,15 +1038,23 @@ async def get( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.orders.get( - site_id="site_id", - order_id="order_id", - ) + + + async def main() -> None: + await client.orders.get( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", @@ -587,21 +1063,83 @@ async def get( ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + return typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -619,7 +1157,9 @@ async def update( request_options: typing.Optional[RequestOptions] = None, ) -> Order: """ - This API lets you update the fields, `comment`, `shippingProvider`, and/or `shippingTracking` for a given order. All three fields can be updated simultaneously or independently. + This API lets you update the fields, `comment`, `shippingProvider`, + and/or `shippingTracking` for a given order. All three fields can be + updated simultaneously or independently. Required scope | `ecommerce:write` @@ -653,15 +1193,23 @@ async def update( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.orders.update( - site_id="site_id", - order_id="order_id", - ) + + + async def main() -> None: + await client.orders.update( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", @@ -672,26 +1220,91 @@ async def update( "shippingTracking": shipping_tracking, "shippingTrackingURL": shipping_tracking_url, }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + return typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -731,40 +1344,115 @@ async def update_fulfill( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.orders.update_fulfill( - site_id="site_id", - order_id="order_id", - ) + + + async def main() -> None: + await client.orders.update_fulfill( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", method="POST", - json={"sendOrderFulfilledEmail": send_order_fulfilled_email}, + json={ + "sendOrderFulfilledEmail": send_order_fulfilled_email, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + return typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -796,15 +1484,23 @@ async def update_unfulfill( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.orders.update_unfulfill( - site_id="site_id", - order_id="order_id", - ) + + + async def main() -> None: + await client.orders.update_unfulfill( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", @@ -813,21 +1509,83 @@ async def update_unfulfill( ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + return typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -868,40 +1626,115 @@ async def refund( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.orders.refund( - site_id="site_id", - order_id="order_id", - ) + + + async def main() -> None: + await client.orders.refund( + site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", method="POST", - json={"reason": reason}, + json={ + "reason": reason, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Order, _response.json()) # type: ignore + return typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/orders/types/orders_list_request_status.py b/src/webflow/resources/orders/types/orders_list_request_status.py index ecdfbca..dfa1af7 100644 --- a/src/webflow/resources/orders/types/orders_list_request_status.py +++ b/src/webflow/resources/orders/types/orders_list_request_status.py @@ -1,37 +1,7 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class OrdersListRequestStatus(str, enum.Enum): - PENDING = "pending" - REFUNDED = "refunded" - DISPUTE_LOST = "dispute-lost" - FULFILLED = "fulfilled" - DISPUTED = "disputed" - UNFULFILLED = "unfulfilled" - - def visit( - self, - pending: typing.Callable[[], T_Result], - refunded: typing.Callable[[], T_Result], - dispute_lost: typing.Callable[[], T_Result], - fulfilled: typing.Callable[[], T_Result], - disputed: typing.Callable[[], T_Result], - unfulfilled: typing.Callable[[], T_Result], - ) -> T_Result: - if self is OrdersListRequestStatus.PENDING: - return pending() - if self is OrdersListRequestStatus.REFUNDED: - return refunded() - if self is OrdersListRequestStatus.DISPUTE_LOST: - return dispute_lost() - if self is OrdersListRequestStatus.FULFILLED: - return fulfilled() - if self is OrdersListRequestStatus.DISPUTED: - return disputed() - if self is OrdersListRequestStatus.UNFULFILLED: - return unfulfilled() +OrdersListRequestStatus = typing.Union[ + typing.Literal["pending", "refunded", "dispute-lost", "fulfilled", "disputed", "unfulfilled"], typing.Any +] diff --git a/src/webflow/resources/orders/types/orders_refund_request_reason.py b/src/webflow/resources/orders/types/orders_refund_request_reason.py index a3025a6..149ae86 100644 --- a/src/webflow/resources/orders/types/orders_refund_request_reason.py +++ b/src/webflow/resources/orders/types/orders_refund_request_reason.py @@ -1,29 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class OrdersRefundRequestReason(str, enum.Enum): - """ - The reason for the refund - """ - - DUPLICATE = "duplicate" - FRAUDULENT = "fraudulent" - REQUESTED = "requested" - - def visit( - self, - duplicate: typing.Callable[[], T_Result], - fraudulent: typing.Callable[[], T_Result], - requested: typing.Callable[[], T_Result], - ) -> T_Result: - if self is OrdersRefundRequestReason.DUPLICATE: - return duplicate() - if self is OrdersRefundRequestReason.FRAUDULENT: - return fraudulent() - if self is OrdersRefundRequestReason.REQUESTED: - return requested() +OrdersRefundRequestReason = typing.Union[typing.Literal["duplicate", "fraudulent", "requested"], typing.Any] diff --git a/src/webflow/resources/pages/__init__.py b/src/webflow/resources/pages/__init__.py index b846071..0fed8e6 100644 --- a/src/webflow/resources/pages/__init__.py +++ b/src/webflow/resources/pages/__init__.py @@ -1,6 +1,6 @@ # This file was auto-generated by Fern from our API Definition. -from .types import DomWriteNodesItem, UpdateStaticContentResponse +from .types import PageDomWriteNodesItem, UpdateStaticContentResponse from .resources import scripts -__all__ = ["DomWriteNodesItem", "UpdateStaticContentResponse", "scripts"] +__all__ = ["PageDomWriteNodesItem", "UpdateStaticContentResponse", "scripts"] diff --git a/src/webflow/resources/pages/client.py b/src/webflow/resources/pages/client.py index 61c1550..851f4e7 100644 --- a/src/webflow/resources/pages/client.py +++ b/src/webflow/resources/pages/client.py @@ -1,28 +1,31 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from ...core.client_wrapper import SyncClientWrapper +from .resources.scripts.client import ScriptsClient from ...core.request_options import RequestOptions +from ...types.page_list import PageList +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError -from ...errors.forbidden_error import ForbiddenError -from ...errors.internal_server_error import InternalServerError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.not_found_error import NotFoundError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.dom import Dom -from ...types.page_details import PageDetails -from ...types.page_list import PageList -from ...types.page_open_graph import PageOpenGraph +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError +from ...types.page import Page +import datetime as dt from ...types.page_seo import PageSeo -from .resources.scripts.client import AsyncScriptsClient, ScriptsClient -from .types.dom_write_nodes_item import DomWriteNodesItem +from ...types.page_open_graph import PageOpenGraph +from ...core.serialization import convert_and_respect_annotation_metadata +from ...types.dom import Dom +from ...errors.forbidden_error import ForbiddenError +from .types.page_dom_write_nodes_item import PageDomWriteNodesItem from .types.update_static_content_response import UpdateStaticContentResponse +from ...core.client_wrapper import AsyncClientWrapper +from .resources.scripts.client import AsyncScriptsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -37,20 +40,22 @@ def list( self, site_id: str, *, - locale: typing.Optional[str] = None, + locale_id: typing.Optional[str] = None, limit: typing.Optional[float] = None, offset: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, ) -> PageList: """ - List of all pages for a site

Required scope | `pages:read` + List of all pages for a site. + + Required scope | `pages:read` Parameters ---------- site_id : str Unique identifier for a Site - locale : typing.Optional[str] + locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. limit : typing.Optional[float] @@ -69,34 +74,85 @@ def list( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.pages.list( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/pages", method="GET", - params={"locale": locale, "limit": limit, "offset": offset}, + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(PageList, _response.json()) # type: ignore + return typing.cast( + PageList, + parse_obj_as( + type_=PageList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -106,18 +162,20 @@ def get_metadata( self, page_id: str, *, - locale: typing.Optional[str] = None, + locale_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> PageDetails: + ) -> Page: """ - Get metadata information for a single page

Required scope | `pages:read` + Get metadata information for a single page. + + Required scope | `pages:read` Parameters ---------- page_id : str Unique identifier for a Page - locale : typing.Optional[str] + locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. request_options : typing.Optional[RequestOptions] @@ -125,39 +183,88 @@ def get_metadata( Returns ------- - PageDetails + Page Request was successful Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.pages.get_metadata( - page_id="page_id", + page_id="63c720f9347c2139b248e552", + locale_id="65427cf400e02b306eaa04a0", ) """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", method="GET", - params={"locale": locale}, + params={ + "localeId": locale_id, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(PageDetails, _response.json()) # type: ignore + return typing.cast( + Page, + parse_obj_as( + type_=Page, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -167,8 +274,8 @@ def update_page_settings( self, page_id: str, *, - locale: typing.Optional[str] = None, - id: typing.Optional[str] = OMIT, + id: str, + locale_id: typing.Optional[str] = None, site_id: typing.Optional[str] = OMIT, title: typing.Optional[str] = OMIT, slug: typing.Optional[str] = OMIT, @@ -179,25 +286,30 @@ def update_page_settings( archived: typing.Optional[bool] = OMIT, draft: typing.Optional[bool] = OMIT, can_branch: typing.Optional[bool] = OMIT, + is_branch: typing.Optional[bool] = OMIT, is_members_only: typing.Optional[bool] = OMIT, seo: typing.Optional[PageSeo] = OMIT, open_graph: typing.Optional[PageOpenGraph] = OMIT, + page_locale_id: typing.Optional[str] = OMIT, + published_path: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> PageDetails: + ) -> Page: """ - Update Page-level metadata, including SEO and Open Graph fields.

Required scope | `pages:write` + Update Page-level metadata, including SEO and Open Graph fields. + + Required scope | `pages:write` Parameters ---------- page_id : str Unique identifier for a Page - locale : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. - - id : typing.Optional[str] + id : str Unique identifier for the Page + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + site_id : typing.Optional[str] Unique identifier for the Site @@ -228,6 +340,9 @@ def update_page_settings( can_branch : typing.Optional[bool] Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) + is_branch : typing.Optional[bool] + Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) + is_members_only : typing.Optional[bool] Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) @@ -237,32 +352,36 @@ def update_page_settings( open_graph : typing.Optional[PageOpenGraph] Open Graph fields for the Page + page_locale_id : typing.Optional[str] + Unique ID of the page locale + + published_path : typing.Optional[str] + Relative path of the published page URL + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - PageDetails + Page Request was successful Examples -------- import datetime - from webflow import PageOpenGraph, PageSeo - from webflow.client import Webflow + from webflow import PageOpenGraph, PageSeo, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.pages.update_page_settings( - page_id="page_id", + page_id="63c720f9347c2139b248e552", + locale_id="65427cf400e02b306eaa04a0", id="6596da6045e56dee495bcbba", site_id="6258612d1ee792848f805dcf", title="Guide to the Galaxy", slug="guide-to-the-galaxy", - parent_id="6419db964a9c435aa3af6251", - collection_id="6390c49774a71f12831a08e3", created_on=datetime.datetime.fromisoformat( "2024-03-11 10:42:00+00:00", ), @@ -272,6 +391,7 @@ def update_page_settings( archived=False, draft=False, can_branch=True, + is_branch=False, seo=PageSeo( title="The Ultimate Hitchhiker's Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", @@ -282,12 +402,16 @@ def update_page_settings( description="Dive deep into the mysteries of the universe with your guide to everything galactic.", description_copied=False, ), + page_locale_id="653fd9af6a07fc9cfd7a5e57", + published_path="/en-us/guide-to-the-galaxy", ) """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", method="PUT", - params={"locale": locale}, + params={ + "localeId": locale_id, + }, json={ "id": id, "siteId": site_id, @@ -300,26 +424,77 @@ def update_page_settings( "archived": archived, "draft": draft, "canBranch": can_branch, + "isBranch": is_branch, "isMembersOnly": is_members_only, - "seo": seo, - "openGraph": open_graph, + "seo": convert_and_respect_annotation_metadata(object_=seo, annotation=PageSeo, direction="write"), + "openGraph": convert_and_respect_annotation_metadata( + object_=open_graph, annotation=PageOpenGraph, direction="write" + ), + "localeId": locale_id, + "publishedPath": published_path, }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(PageDetails, _response.json()) # type: ignore + return typing.cast( + Page, + parse_obj_as( + type_=Page, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -329,20 +504,25 @@ def get_content( self, page_id: str, *, - locale: typing.Optional[str] = None, + locale_id: typing.Optional[str] = None, limit: typing.Optional[float] = None, offset: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, ) -> Dom: """ - Get static content from a static page.
If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale

Required scope | `pages:read` + Get static content from a static page. This includes text nodes, image nodes and component instances. + To retrieve the contents of components in the page use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint. + + If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + + Required scope | `pages:read` Parameters ---------- page_id : str Unique identifier for a Page - locale : typing.Optional[str] + locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. limit : typing.Optional[float] @@ -361,36 +541,95 @@ def get_content( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.pages.get_content( - page_id="page_id", + page_id="63c720f9347c2139b248e552", + locale_id="65427cf400e02b306eaa04a0", ) """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", method="GET", - params={"locale": locale, "limit": limit, "offset": offset}, + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Dom, _response.json()) # type: ignore + return typing.cast( + Dom, + parse_obj_as( + type_=Dom, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -400,22 +639,33 @@ def update_static_content( self, page_id: str, *, - locale: str, - nodes: typing.Sequence[DomWriteNodesItem], + locale_id: str, + nodes: typing.Sequence[PageDomWriteNodesItem], request_options: typing.Optional[RequestOptions] = None, ) -> UpdateStaticContentResponse: """ - Update static content on a static page. This endpoint supports sending 1000 nodes per request.

Required scope | `pages:write` + This endpoint updates content on a static page in **secondary locales**. It supports updating up to 1000 nodes in a single request. + + Before making updates: + 1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) endpoint to identify available content nodes and their types + 2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint + + + This endpoint is specifically for localized pages. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + + Required scope | `pages:write` Parameters ---------- page_id : str Unique identifier for a Page - locale : str + locale_id : str The locale identifier. - nodes : typing.Sequence[DomWriteNodesItem] + nodes : typing.Sequence[PageDomWriteNodesItem] + List of DOM Nodes with the new content that will be updated in each node. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -427,27 +677,40 @@ def update_static_content( Examples -------- - from webflow import DomWriteNodesItem - from webflow.client import Webflow + from webflow import ( + ComponentInstanceNodePropertyOverridesWrite, + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + TextNodeWrite, + Webflow, + ) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.pages.update_static_content( - page_id="page_id", - locale="locale", + page_id="63c720f9347c2139b248e552", + locale_id="localeId", nodes=[ - DomWriteNodesItem( + TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

", ), - DomWriteNodesItem( + TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Don't Panic!

Always know where your towel is.

", ), - DomWriteNodesItem( + ComponentInstanceNodePropertyOverridesWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", - text="Marvin, the Paranoid Android", + property_overrides=[ + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", + text="

Time is an illusion

", + ), + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", + text="Life, the Universe and Everything", + ), + ], ), ], ) @@ -455,26 +718,89 @@ def update_static_content( _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", method="POST", - params={"locale": locale}, - json={"nodes": nodes}, + params={ + "localeId": locale_id, + }, + json={ + "nodes": convert_and_respect_annotation_metadata( + object_=nodes, annotation=typing.Sequence[PageDomWriteNodesItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(UpdateStaticContentResponse, _response.json()) # type: ignore + return typing.cast( + UpdateStaticContentResponse, + parse_obj_as( + type_=UpdateStaticContentResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -490,20 +816,22 @@ async def list( self, site_id: str, *, - locale: typing.Optional[str] = None, + locale_id: typing.Optional[str] = None, limit: typing.Optional[float] = None, offset: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, ) -> PageList: """ - List of all pages for a site

Required scope | `pages:read` + List of all pages for a site. + + Required scope | `pages:read` Parameters ---------- site_id : str Unique identifier for a Site - locale : typing.Optional[str] + locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. limit : typing.Optional[float] @@ -522,34 +850,93 @@ async def list( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.pages.list( - site_id="site_id", - ) + + + async def main() -> None: + await client.pages.list( + site_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/pages", method="GET", - params={"locale": locale, "limit": limit, "offset": offset}, + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(PageList, _response.json()) # type: ignore + return typing.cast( + PageList, + parse_obj_as( + type_=PageList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -559,18 +946,20 @@ async def get_metadata( self, page_id: str, *, - locale: typing.Optional[str] = None, + locale_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> PageDetails: + ) -> Page: """ - Get metadata information for a single page

Required scope | `pages:read` + Get metadata information for a single page. + + Required scope | `pages:read` Parameters ---------- page_id : str Unique identifier for a Page - locale : typing.Optional[str] + locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. request_options : typing.Optional[RequestOptions] @@ -578,39 +967,96 @@ async def get_metadata( Returns ------- - PageDetails + Page Request was successful Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.pages.get_metadata( - page_id="page_id", - ) + + + async def main() -> None: + await client.pages.get_metadata( + page_id="63c720f9347c2139b248e552", + locale_id="65427cf400e02b306eaa04a0", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", method="GET", - params={"locale": locale}, + params={ + "localeId": locale_id, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(PageDetails, _response.json()) # type: ignore + return typing.cast( + Page, + parse_obj_as( + type_=Page, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -620,8 +1066,8 @@ async def update_page_settings( self, page_id: str, *, - locale: typing.Optional[str] = None, - id: typing.Optional[str] = OMIT, + id: str, + locale_id: typing.Optional[str] = None, site_id: typing.Optional[str] = OMIT, title: typing.Optional[str] = OMIT, slug: typing.Optional[str] = OMIT, @@ -632,25 +1078,30 @@ async def update_page_settings( archived: typing.Optional[bool] = OMIT, draft: typing.Optional[bool] = OMIT, can_branch: typing.Optional[bool] = OMIT, + is_branch: typing.Optional[bool] = OMIT, is_members_only: typing.Optional[bool] = OMIT, seo: typing.Optional[PageSeo] = OMIT, open_graph: typing.Optional[PageOpenGraph] = OMIT, + page_locale_id: typing.Optional[str] = OMIT, + published_path: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> PageDetails: + ) -> Page: """ - Update Page-level metadata, including SEO and Open Graph fields.

Required scope | `pages:write` + Update Page-level metadata, including SEO and Open Graph fields. + + Required scope | `pages:write` Parameters ---------- page_id : str Unique identifier for a Page - locale : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. - - id : typing.Optional[str] + id : str Unique identifier for the Page + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + site_id : typing.Optional[str] Unique identifier for the Site @@ -681,6 +1132,9 @@ async def update_page_settings( can_branch : typing.Optional[bool] Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) + is_branch : typing.Optional[bool] + Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) + is_members_only : typing.Optional[bool] Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) @@ -690,57 +1144,73 @@ async def update_page_settings( open_graph : typing.Optional[PageOpenGraph] Open Graph fields for the Page + page_locale_id : typing.Optional[str] + Unique ID of the page locale + + published_path : typing.Optional[str] + Relative path of the published page URL + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - PageDetails + Page Request was successful Examples -------- + import asyncio import datetime - from webflow import PageOpenGraph, PageSeo - from webflow.client import AsyncWebflow + from webflow import AsyncWebflow, PageOpenGraph, PageSeo client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.pages.update_page_settings( - page_id="page_id", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", - title="Guide to the Galaxy", - slug="guide-to-the-galaxy", - parent_id="6419db964a9c435aa3af6251", - collection_id="6390c49774a71f12831a08e3", - created_on=datetime.datetime.fromisoformat( - "2024-03-11 10:42:00+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2024-03-11 10:42:42+00:00", - ), - archived=False, - draft=False, - can_branch=True, - seo=PageSeo( - title="The Ultimate Hitchhiker's Guide to the Galaxy", - description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", - ), - open_graph=PageOpenGraph( - title="Explore the Cosmos with The Ultimate Guide", - title_copied=False, - description="Dive deep into the mysteries of the universe with your guide to everything galactic.", - description_copied=False, - ), - ) + + + async def main() -> None: + await client.pages.update_page_settings( + page_id="63c720f9347c2139b248e552", + locale_id="65427cf400e02b306eaa04a0", + id="6596da6045e56dee495bcbba", + site_id="6258612d1ee792848f805dcf", + title="Guide to the Galaxy", + slug="guide-to-the-galaxy", + created_on=datetime.datetime.fromisoformat( + "2024-03-11 10:42:00+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2024-03-11 10:42:42+00:00", + ), + archived=False, + draft=False, + can_branch=True, + is_branch=False, + seo=PageSeo( + title="The Ultimate Hitchhiker's Guide to the Galaxy", + description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", + ), + open_graph=PageOpenGraph( + title="Explore the Cosmos with The Ultimate Guide", + title_copied=False, + description="Dive deep into the mysteries of the universe with your guide to everything galactic.", + description_copied=False, + ), + page_locale_id="653fd9af6a07fc9cfd7a5e57", + published_path="/en-us/guide-to-the-galaxy", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", method="PUT", - params={"locale": locale}, + params={ + "localeId": locale_id, + }, json={ "id": id, "siteId": site_id, @@ -753,26 +1223,77 @@ async def update_page_settings( "archived": archived, "draft": draft, "canBranch": can_branch, + "isBranch": is_branch, "isMembersOnly": is_members_only, - "seo": seo, - "openGraph": open_graph, + "seo": convert_and_respect_annotation_metadata(object_=seo, annotation=PageSeo, direction="write"), + "openGraph": convert_and_respect_annotation_metadata( + object_=open_graph, annotation=PageOpenGraph, direction="write" + ), + "localeId": locale_id, + "publishedPath": published_path, }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(PageDetails, _response.json()) # type: ignore + return typing.cast( + Page, + parse_obj_as( + type_=Page, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -782,20 +1303,25 @@ async def get_content( self, page_id: str, *, - locale: typing.Optional[str] = None, + locale_id: typing.Optional[str] = None, limit: typing.Optional[float] = None, offset: typing.Optional[float] = None, request_options: typing.Optional[RequestOptions] = None, ) -> Dom: """ - Get static content from a static page.
If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale

Required scope | `pages:read` + Get static content from a static page. This includes text nodes, image nodes and component instances. + To retrieve the contents of components in the page use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint. + + If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + + Required scope | `pages:read` Parameters ---------- page_id : str Unique identifier for a Page - locale : typing.Optional[str] + locale_id : typing.Optional[str] Unique identifier for a specific locale. Applicable, when using localization. limit : typing.Optional[float] @@ -814,36 +1340,103 @@ async def get_content( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.pages.get_content( - page_id="page_id", - ) + + + async def main() -> None: + await client.pages.get_content( + page_id="63c720f9347c2139b248e552", + locale_id="65427cf400e02b306eaa04a0", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", method="GET", - params={"locale": locale, "limit": limit, "offset": offset}, + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Dom, _response.json()) # type: ignore + return typing.cast( + Dom, + parse_obj_as( + type_=Dom, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -853,22 +1446,33 @@ async def update_static_content( self, page_id: str, *, - locale: str, - nodes: typing.Sequence[DomWriteNodesItem], + locale_id: str, + nodes: typing.Sequence[PageDomWriteNodesItem], request_options: typing.Optional[RequestOptions] = None, ) -> UpdateStaticContentResponse: """ - Update static content on a static page. This endpoint supports sending 1000 nodes per request.

Required scope | `pages:write` + This endpoint updates content on a static page in **secondary locales**. It supports updating up to 1000 nodes in a single request. + + Before making updates: + 1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) endpoint to identify available content nodes and their types + 2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint + + + This endpoint is specifically for localized pages. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + + Required scope | `pages:write` Parameters ---------- page_id : str Unique identifier for a Page - locale : str + locale_id : str The locale identifier. - nodes : typing.Sequence[DomWriteNodesItem] + nodes : typing.Sequence[PageDomWriteNodesItem] + List of DOM Nodes with the new content that will be updated in each node. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -880,54 +1484,138 @@ async def update_static_content( Examples -------- - from webflow import DomWriteNodesItem - from webflow.client import AsyncWebflow + import asyncio + + from webflow import ( + AsyncWebflow, + ComponentInstanceNodePropertyOverridesWrite, + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + TextNodeWrite, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.pages.update_static_content( - page_id="page_id", - locale="locale", - nodes=[ - DomWriteNodesItem( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", - text="

The Hitchhiker's Guide to the Galaxy

", - ), - DomWriteNodesItem( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", - text="

Don't Panic!

Always know where your towel is.

", - ), - DomWriteNodesItem( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", - text="Marvin, the Paranoid Android", - ), - ], - ) + + + async def main() -> None: + await client.pages.update_static_content( + page_id="63c720f9347c2139b248e552", + locale_id="localeId", + nodes=[ + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", + text="

The Hitchhiker's Guide to the Galaxy

", + ), + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + ComponentInstanceNodePropertyOverridesWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + property_overrides=[ + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", + text="

Time is an illusion

", + ), + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", + text="Life, the Universe and Everything", + ), + ], + ), + ], + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", method="POST", - params={"locale": locale}, - json={"nodes": nodes}, + params={ + "localeId": locale_id, + }, + json={ + "nodes": convert_and_respect_annotation_metadata( + object_=nodes, annotation=typing.Sequence[PageDomWriteNodesItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(UpdateStaticContentResponse, _response.json()) # type: ignore + return typing.cast( + UpdateStaticContentResponse, + parse_obj_as( + type_=UpdateStaticContentResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/pages/resources/scripts/client.py b/src/webflow/resources/pages/resources/scripts/client.py index 1895650..56bd39a 100644 --- a/src/webflow/resources/pages/resources/scripts/client.py +++ b/src/webflow/resources/pages/resources/scripts/client.py @@ -1,20 +1,23 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from .....core.api_error import ApiError -from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import pydantic_v1 +from .....core.client_wrapper import SyncClientWrapper from .....core.request_options import RequestOptions +from .....types.script_apply_list import ScriptApplyList +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as from .....errors.bad_request_error import BadRequestError -from .....errors.internal_server_error import InternalServerError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error from .....errors.not_found_error import NotFoundError from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.unauthorized_error import UnauthorizedError +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError from .....types.script_apply import ScriptApply -from .....types.script_apply_list import ScriptApplyList +from .....core.serialization import convert_and_respect_annotation_metadata +from .....errors.conflict_error import ConflictError +from .....core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -28,7 +31,15 @@ def get_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + Get all registered scripts that have been applied to a specific Page. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:read` Parameters ---------- @@ -45,31 +56,79 @@ def get_custom_code( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.pages.scripts.get_custom_code( - page_id="page_id", + page_id="63c720f9347c2139b248e552", ) """ _response = self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/custom_code", method="GET", request_options=request_options + f"pages/{jsonable_encoder(page_id)}/custom_code", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + return typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -85,7 +144,17 @@ def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + Add a registered script to a Page. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + + A site can have a maximum of 800 registered scripts. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -111,24 +180,23 @@ def upsert_custom_code( Examples -------- - from webflow import ScriptApply, ScriptApplyLocation - from webflow.client import Webflow + from webflow import ScriptApply, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.pages.scripts.upsert_custom_code( - page_id="page_id", + page_id="63c720f9347c2139b248e552", scripts=[ ScriptApply( id="cms_slider", - location=ScriptApplyLocation.HEADER, + location="header", version="1.0.0", attributes={"my-attribute": "some-value"}, ), ScriptApply( id="alert", - location=ScriptApplyLocation.HEADER, + location="header", version="0.0.1", ), ], @@ -137,23 +205,85 @@ def upsert_custom_code( _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", method="PUT", - json={"scripts": scripts, "lastUpdated": last_updated, "createdOn": created_on}, + json={ + "scripts": convert_and_respect_annotation_metadata( + object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" + ), + "lastUpdated": last_updated, + "createdOn": created_on, + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + return typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -161,7 +291,15 @@ def upsert_custom_code( def delete_custom_code(self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete the custom code block that an app has created for a page

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + Delete the custom code block that an app has created for a page + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -177,31 +315,73 @@ def delete_custom_code(self, page_id: str, *, request_options: typing.Optional[R Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.pages.scripts.delete_custom_code( - page_id="page_id", + page_id="63c720f9347c2139b248e552", ) """ _response = self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/custom_code", method="DELETE", request_options=request_options + f"pages/{jsonable_encoder(page_id)}/custom_code", + method="DELETE", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -216,7 +396,15 @@ async def get_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + Get all registered scripts that have been applied to a specific Page. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:read` Parameters ---------- @@ -233,31 +421,87 @@ async def get_custom_code( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.pages.scripts.get_custom_code( - page_id="page_id", - ) + + + async def main() -> None: + await client.pages.scripts.get_custom_code( + page_id="63c720f9347c2139b248e552", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/custom_code", method="GET", request_options=request_options + f"pages/{jsonable_encoder(page_id)}/custom_code", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + return typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -273,7 +517,17 @@ async def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Page.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + Add a registered script to a Page. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + + A site can have a maximum of 800 registered scripts. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -299,49 +553,118 @@ async def upsert_custom_code( Examples -------- - from webflow import ScriptApply, ScriptApplyLocation - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow, ScriptApply client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.pages.scripts.upsert_custom_code( - page_id="page_id", - scripts=[ - ScriptApply( - id="cms_slider", - location=ScriptApplyLocation.HEADER, - version="1.0.0", - attributes={"my-attribute": "some-value"}, - ), - ScriptApply( - id="alert", - location=ScriptApplyLocation.HEADER, - version="0.0.1", - ), - ], - ) + + + async def main() -> None: + await client.pages.scripts.upsert_custom_code( + page_id="63c720f9347c2139b248e552", + scripts=[ + ScriptApply( + id="cms_slider", + location="header", + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location="header", + version="0.0.1", + ), + ], + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", method="PUT", - json={"scripts": scripts, "lastUpdated": last_updated, "createdOn": created_on}, + json={ + "scripts": convert_and_respect_annotation_metadata( + object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" + ), + "lastUpdated": last_updated, + "createdOn": created_on, + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + return typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -351,7 +674,15 @@ async def delete_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> None: """ - Delete the custom code block that an app has created for a page

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + Delete the custom code block that an app has created for a page + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -367,31 +698,81 @@ async def delete_custom_code( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.pages.scripts.delete_custom_code( - page_id="page_id", - ) + + + async def main() -> None: + await client.pages.scripts.delete_custom_code( + page_id="63c720f9347c2139b248e552", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/custom_code", method="DELETE", request_options=request_options + f"pages/{jsonable_encoder(page_id)}/custom_code", + method="DELETE", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/pages/types/__init__.py b/src/webflow/resources/pages/types/__init__.py index 0903928..08c0325 100644 --- a/src/webflow/resources/pages/types/__init__.py +++ b/src/webflow/resources/pages/types/__init__.py @@ -1,6 +1,6 @@ # This file was auto-generated by Fern from our API Definition. -from .dom_write_nodes_item import DomWriteNodesItem +from .page_dom_write_nodes_item import PageDomWriteNodesItem from .update_static_content_response import UpdateStaticContentResponse -__all__ = ["DomWriteNodesItem", "UpdateStaticContentResponse"] +__all__ = ["PageDomWriteNodesItem", "UpdateStaticContentResponse"] diff --git a/src/webflow/resources/pages/types/dom_write_nodes_item.py b/src/webflow/resources/pages/types/dom_write_nodes_item.py deleted file mode 100644 index b37b43b..0000000 --- a/src/webflow/resources/pages/types/dom_write_nodes_item.py +++ /dev/null @@ -1,39 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ....core.datetime_utils import serialize_datetime -from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - - -class DomWriteNodesItem(pydantic_v1.BaseModel): - node_id: str = pydantic_v1.Field(alias="nodeId") - """ - Node UUID - """ - - text: str = pydantic_v1.Field() - """ - HTML content of the node, including the HTML tag. The HTML tags must be the same as what's returned from the Get Content endpoint. - """ - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/resources/pages/types/page_dom_write_nodes_item.py b/src/webflow/resources/pages/types/page_dom_write_nodes_item.py new file mode 100644 index 0000000..05d1f3f --- /dev/null +++ b/src/webflow/resources/pages/types/page_dom_write_nodes_item.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ....types.text_node_write import TextNodeWrite +from ....types.component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite + +PageDomWriteNodesItem = typing.Union[TextNodeWrite, ComponentInstanceNodePropertyOverridesWrite] diff --git a/src/webflow/resources/pages/types/update_static_content_response.py b/src/webflow/resources/pages/types/update_static_content_response.py index f960341..0bcf93a 100644 --- a/src/webflow/resources/pages/types/update_static_content_response.py +++ b/src/webflow/resources/pages/types/update_static_content_response.py @@ -1,32 +1,22 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ....core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2 -from ....core.datetime_utils import serialize_datetime -from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class UpdateStaticContentResponse(pydantic_v1.BaseModel): - errors: typing.List[str] = pydantic_v1.Field() +class UpdateStaticContentResponse(UniversalBaseModel): + errors: typing.List[str] = pydantic.Field() """ A list of error messages, if any. """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/products/client.py b/src/webflow/resources/products/client.py index fb1896e..c856fef 100644 --- a/src/webflow/resources/products/client.py +++ b/src/webflow/resources/products/client.py @@ -1,26 +1,28 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from ...core.client_wrapper import SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.product_and_sk_us_list import ProductAndSkUsList +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError -from ...errors.conflict_error import ConflictError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.forbidden_error import ForbiddenError -from ...errors.internal_server_error import InternalServerError from ...errors.not_found_error import NotFoundError +from ...errors.conflict_error import ConflictError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.product import Product -from ...types.product_and_sk_us import ProductAndSkUs -from ...types.product_and_sk_us_list import ProductAndSkUsList +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError from ...types.publish_status import PublishStatus +from ...types.product import Product from ...types.sku import Sku +from ...types.product_and_sk_us import ProductAndSkUs +from ...core.serialization import convert_and_respect_annotation_metadata from .types.products_create_sku_response import ProductsCreateSkuResponse +from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -39,7 +41,10 @@ def list( request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUsList: """ - Retrieve all products for a site. Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. + Retrieve all products for a site. + + Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product + will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. Required scope | `ecommerce:read` @@ -64,38 +69,103 @@ def list( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.products.list( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", method="GET", - params={"offset": offset, "limit": limit}, + params={ + "offset": offset, + "limit": limit, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ProductAndSkUsList, _response.json()) # type: ignore + return typing.cast( + ProductAndSkUsList, + parse_obj_as( + type_=ProductAndSkUsList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -111,13 +181,18 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUs: """ - Creating a new Product involves creating both a Product and a SKU, since a Product Item has to have, at minimum, a single SKU. + Create a new product and SKU. - In order to create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large - you'll need to create `sku-properties`. In our T-shirt example, a single `sku-property` would be Color. Within that property, we'll need to list out the various colors a T-shirt could be as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. + When you create a product, you will always create a SKU, since a Product Item must have, at minimum, a single SKU. - Once, you've created a Product and its `sku-properties` with `enum` values, you can create your default SKU, which will automatically be a combination of the first `sku-properties` you've created. In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. After you've created your product, you can create additional SKUs using the Create SKU endpoint + To create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large: + - Create parameters in `sku-properties`, also known as [product options and variants.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). + - A single `sku-property` would be `color`. Within the `color` property, list the various colors of T-shirts as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. + - Once, you've created a Product and its `sku-properties` with `enum` values, Webflow will create a **default SKU**, which will automatically be a combination of the first `sku-properties` you've created. + - In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. + - After you've created your product, you can create additional SKUs using the [Create SKU endpoint.](/data/reference/ecommerce/products/create-sku) - Upon creation, the default product type will be `Advanced`. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. + Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. Required scope | `ecommerce:write` @@ -142,39 +217,110 @@ def create( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.products.create( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", method="POST", - json={"publishStatus": publish_status, "product": product, "sku": sku}, + json={ + "publishStatus": publish_status, + "product": convert_and_respect_annotation_metadata( + object_=product, annotation=Product, direction="write" + ), + "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore + return typing.cast( + ProductAndSkUs, + parse_obj_as( + type_=ProductAndSkUs, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -184,7 +330,8 @@ def get( self, site_id: str, product_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ProductAndSkUs: """ - Retrieve a single product by its id. All of its SKUs will also be retrieved. + Retrieve a single product by its ID. All of its SKUs will also be + retrieved. Required scope | `ecommerce:read` @@ -206,14 +353,14 @@ def get( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.products.get( - site_id="site_id", - product_id="product_id", + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", ) """ _response = self._client_wrapper.httpx_client.request( @@ -223,21 +370,83 @@ def get( ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore + return typing.cast( + ProductAndSkUs, + parse_obj_as( + type_=ProductAndSkUs, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -254,7 +463,9 @@ def update( request_options: typing.Optional[RequestOptions] = None, ) -> Product: """ - Updating an existing Product will set the product type to `Advanced`. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. + Update an existing Product. + + Updating an existing Product will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. Required scope | `ecommerce:write` @@ -282,40 +493,111 @@ def update( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.products.update( - site_id="site_id", - product_id="product_id", + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", method="PATCH", - json={"publishStatus": publish_status, "product": product, "sku": sku}, + json={ + "publishStatus": publish_status, + "product": convert_and_respect_annotation_metadata( + object_=product, annotation=Product, direction="write" + ), + "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Product, _response.json()) # type: ignore + return typing.cast( + Product, + parse_obj_as( + type_=Product, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -331,9 +613,9 @@ def create_sku( request_options: typing.Optional[RequestOptions] = None, ) -> ProductsCreateSkuResponse: """ - Create additional SKUs to cover every variant of your Product. The Default SKU already counts as one of the variants. + Create additional SKUs to manage every [option and variant of your Product.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants) - Creating additional SKUs will set the product type to `Advanced` for the product associated with the SKUs. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. + Creating SKUs through the API will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. Required scope | `ecommerce:write` @@ -360,42 +642,111 @@ def create_sku( Examples -------- - from webflow import Sku - from webflow.client import Webflow + from webflow import Sku, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.products.create_sku( - site_id="site_id", - product_id="product_id", + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", skus=[Sku()], ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", method="POST", - json={"publishStatus": publish_status, "skus": skus}, + json={ + "publishStatus": publish_status, + "skus": convert_and_respect_annotation_metadata( + object_=skus, annotation=typing.Sequence[Sku], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ProductsCreateSkuResponse, _response.json()) # type: ignore + return typing.cast( + ProductsCreateSkuResponse, + parse_obj_as( + type_=ProductsCreateSkuResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -412,7 +763,9 @@ def update_sku( request_options: typing.Optional[RequestOptions] = None, ) -> Sku: """ - Updating an existing SKU will set the product type to `Advanced` for the product associated with the SKU. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. + Update a specified SKU. + + Updating an existing SKU will set the Product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. Required scope | `ecommerce:write` @@ -441,43 +794,110 @@ def update_sku( Examples -------- - from webflow import Sku - from webflow.client import Webflow + from webflow import Sku, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.products.update_sku( - site_id="site_id", - product_id="product_id", - sku_id="sku_id", + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + sku_id="5e8518516e147040726cc415", sku=Sku(), ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", method="PATCH", - json={"publishStatus": publish_status, "sku": sku}, + json={ + "publishStatus": publish_status, + "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Sku, _response.json()) # type: ignore + return typing.cast( + Sku, + parse_obj_as( + type_=Sku, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -497,7 +917,10 @@ async def list( request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUsList: """ - Retrieve all products for a site. Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. + Retrieve all products for a site. + + Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product + will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. Required scope | `ecommerce:read` @@ -522,38 +945,111 @@ async def list( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.products.list( - site_id="site_id", - ) + + + async def main() -> None: + await client.products.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", method="GET", - params={"offset": offset, "limit": limit}, + params={ + "offset": offset, + "limit": limit, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ProductAndSkUsList, _response.json()) # type: ignore + return typing.cast( + ProductAndSkUsList, + parse_obj_as( + type_=ProductAndSkUsList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -569,13 +1065,18 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUs: """ - Creating a new Product involves creating both a Product and a SKU, since a Product Item has to have, at minimum, a single SKU. + Create a new product and SKU. - In order to create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large - you'll need to create `sku-properties`. In our T-shirt example, a single `sku-property` would be Color. Within that property, we'll need to list out the various colors a T-shirt could be as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. + When you create a product, you will always create a SKU, since a Product Item must have, at minimum, a single SKU. - Once, you've created a Product and its `sku-properties` with `enum` values, you can create your default SKU, which will automatically be a combination of the first `sku-properties` you've created. In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. After you've created your product, you can create additional SKUs using the Create SKU endpoint + To create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large: + - Create parameters in `sku-properties`, also known as [product options and variants.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). + - A single `sku-property` would be `color`. Within the `color` property, list the various colors of T-shirts as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. + - Once, you've created a Product and its `sku-properties` with `enum` values, Webflow will create a **default SKU**, which will automatically be a combination of the first `sku-properties` you've created. + - In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. + - After you've created your product, you can create additional SKUs using the [Create SKU endpoint.](/data/reference/ecommerce/products/create-sku) - Upon creation, the default product type will be `Advanced`. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. + Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. Required scope | `ecommerce:write` @@ -600,39 +1101,118 @@ async def create( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.products.create( - site_id="site_id", - ) + + + async def main() -> None: + await client.products.create( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", method="POST", - json={"publishStatus": publish_status, "product": product, "sku": sku}, + json={ + "publishStatus": publish_status, + "product": convert_and_respect_annotation_metadata( + object_=product, annotation=Product, direction="write" + ), + "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore + return typing.cast( + ProductAndSkUs, + parse_obj_as( + type_=ProductAndSkUs, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -642,7 +1222,8 @@ async def get( self, site_id: str, product_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ProductAndSkUs: """ - Retrieve a single product by its id. All of its SKUs will also be retrieved. + Retrieve a single product by its ID. All of its SKUs will also be + retrieved. Required scope | `ecommerce:read` @@ -664,15 +1245,23 @@ async def get( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.products.get( - site_id="site_id", - product_id="product_id", - ) + + + async def main() -> None: + await client.products.get( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", @@ -681,21 +1270,83 @@ async def get( ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ProductAndSkUs, _response.json()) # type: ignore + return typing.cast( + ProductAndSkUs, + parse_obj_as( + type_=ProductAndSkUs, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -712,7 +1363,9 @@ async def update( request_options: typing.Optional[RequestOptions] = None, ) -> Product: """ - Updating an existing Product will set the product type to `Advanced`. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. + Update an existing Product. + + Updating an existing Product will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. Required scope | `ecommerce:write` @@ -740,40 +1393,119 @@ async def update( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.products.update( - site_id="site_id", - product_id="product_id", - ) + + + async def main() -> None: + await client.products.update( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", method="PATCH", - json={"publishStatus": publish_status, "product": product, "sku": sku}, + json={ + "publishStatus": publish_status, + "product": convert_and_respect_annotation_metadata( + object_=product, annotation=Product, direction="write" + ), + "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Product, _response.json()) # type: ignore + return typing.cast( + Product, + parse_obj_as( + type_=Product, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -789,9 +1521,9 @@ async def create_sku( request_options: typing.Optional[RequestOptions] = None, ) -> ProductsCreateSkuResponse: """ - Create additional SKUs to cover every variant of your Product. The Default SKU already counts as one of the variants. + Create additional SKUs to manage every [option and variant of your Product.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants) - Creating additional SKUs will set the product type to `Advanced` for the product associated with the SKUs. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. + Creating SKUs through the API will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. Required scope | `ecommerce:write` @@ -818,42 +1550,119 @@ async def create_sku( Examples -------- - from webflow import Sku - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow, Sku client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.products.create_sku( - site_id="site_id", - product_id="product_id", - skus=[Sku()], - ) + + + async def main() -> None: + await client.products.create_sku( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + skus=[Sku()], + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", method="POST", - json={"publishStatus": publish_status, "skus": skus}, + json={ + "publishStatus": publish_status, + "skus": convert_and_respect_annotation_metadata( + object_=skus, annotation=typing.Sequence[Sku], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ProductsCreateSkuResponse, _response.json()) # type: ignore + return typing.cast( + ProductsCreateSkuResponse, + parse_obj_as( + type_=ProductsCreateSkuResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -870,7 +1679,9 @@ async def update_sku( request_options: typing.Optional[RequestOptions] = None, ) -> Sku: """ - Updating an existing SKU will set the product type to `Advanced` for the product associated with the SKU. The product type is used to determine which Product and SKU fields are shown to users in the `Designer` and the `Editor`. Setting it to `Advanced` ensures that all Product and SKU fields will be shown. The product type can be edited in the `Designer` or the `Editor`. + Update a specified SKU. + + Updating an existing SKU will set the Product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. Required scope | `ecommerce:write` @@ -899,43 +1710,118 @@ async def update_sku( Examples -------- - from webflow import Sku - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow, Sku client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.products.update_sku( - site_id="site_id", - product_id="product_id", - sku_id="sku_id", - sku=Sku(), - ) + + + async def main() -> None: + await client.products.update_sku( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + sku_id="5e8518516e147040726cc415", + sku=Sku(), + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", method="PATCH", - json={"publishStatus": publish_status, "sku": sku}, + json={ + "publishStatus": publish_status, + "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Sku, _response.json()) # type: ignore + return typing.cast( + Sku, + parse_obj_as( + type_=Sku, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/products/types/products_create_sku_response.py b/src/webflow/resources/products/types/products_create_sku_response.py index ddff764..e694930 100644 --- a/src/webflow/resources/products/types/products_create_sku_response.py +++ b/src/webflow/resources/products/types/products_create_sku_response.py @@ -1,30 +1,20 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ....core.pydantic_utilities import UniversalBaseModel import typing - -from ....core.datetime_utils import serialize_datetime -from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from ....types.sku import Sku +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class ProductsCreateSkuResponse(pydantic_v1.BaseModel): +class ProductsCreateSkuResponse(UniversalBaseModel): skus: typing.Optional[typing.List[Sku]] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/scripts/client.py b/src/webflow/resources/scripts/client.py index 473d57e..e9112fb 100644 --- a/src/webflow/resources/scripts/client.py +++ b/src/webflow/resources/scripts/client.py @@ -1,21 +1,22 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from ...core.client_wrapper import SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.registered_script_list import RegisteredScriptList +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError -from ...errors.internal_server_error import InternalServerError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.not_found_error import NotFoundError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError from ...types.custom_code_hosted_response import CustomCodeHostedResponse from ...types.custom_code_inline_response import CustomCodeInlineResponse -from ...types.registered_script_list import RegisteredScriptList +from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -27,7 +28,16 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> RegisteredScriptList: """ - List of scripts registered to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + List of scripts registered to a Site. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + Additionally, Scripts can be remotely hosted, or registered as inline snippets. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:read` Parameters ---------- @@ -44,31 +54,79 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.scripts.list( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/registered_scripts", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/registered_scripts", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(RegisteredScriptList, _response.json()) # type: ignore + return typing.cast( + RegisteredScriptList, + parse_obj_as( + type_=RegisteredScriptList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -86,7 +144,16 @@ def register_hosted( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeHostedResponse: """ - Add a script to a Site's Custom Code registry.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.


Required scope | `custom_code:write` + Add a script to a Site's Custom Code registry. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + Additionally, Scripts can be remotely hosted, or registered as inline snippets. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -118,13 +185,13 @@ def register_hosted( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.scripts.register_hosted( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", hosted_location="hostedLocation", integrity_hash="integrityHash", version="version", @@ -141,22 +208,71 @@ def register_hosted( "version": version, "displayName": display_name, }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CustomCodeHostedResponse, _response.json()) # type: ignore + return typing.cast( + CustomCodeHostedResponse, + parse_obj_as( + type_=CustomCodeHostedResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -174,7 +290,15 @@ def register_inline( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeInlineResponse: """ - Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -206,13 +330,13 @@ def register_inline( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.scripts.register_inline( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", source_code="alert('hello world');", version="0.0.1", display_name="Alert", @@ -228,22 +352,71 @@ def register_inline( "version": version, "displayName": display_name, }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CustomCodeInlineResponse, _response.json()) # type: ignore + return typing.cast( + CustomCodeInlineResponse, + parse_obj_as( + type_=CustomCodeInlineResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -258,7 +431,16 @@ async def list( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> RegisteredScriptList: """ - List of scripts registered to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + List of scripts registered to a Site. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + Additionally, Scripts can be remotely hosted, or registered as inline snippets. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:read` Parameters ---------- @@ -275,31 +457,87 @@ async def list( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.scripts.list( - site_id="site_id", - ) + + + async def main() -> None: + await client.scripts.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/registered_scripts", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/registered_scripts", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(RegisteredScriptList, _response.json()) # type: ignore + return typing.cast( + RegisteredScriptList, + parse_obj_as( + type_=RegisteredScriptList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -317,7 +555,16 @@ async def register_hosted( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeHostedResponse: """ - Add a script to a Site's Custom Code registry.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints. Additionally, Scripts can be remotely hosted, or registered as inline snippets.
Access to this endpoint requires a bearer token from a Data Client App.


Required scope | `custom_code:write` + Add a script to a Site's Custom Code registry. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + Additionally, Scripts can be remotely hosted, or registered as inline snippets. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -349,18 +596,26 @@ async def register_hosted( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.scripts.register_hosted( - site_id="site_id", - hosted_location="hostedLocation", - integrity_hash="integrityHash", - version="version", - display_name="displayName", - ) + + + async def main() -> None: + await client.scripts.register_hosted( + site_id="580e63e98c9a982ac9b8b741", + hosted_location="hostedLocation", + integrity_hash="integrityHash", + version="version", + display_name="displayName", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", @@ -372,22 +627,71 @@ async def register_hosted( "version": version, "displayName": display_name, }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CustomCodeHostedResponse, _response.json()) # type: ignore + return typing.cast( + CustomCodeHostedResponse, + parse_obj_as( + type_=CustomCodeHostedResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -405,7 +709,15 @@ async def register_inline( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeInlineResponse: """ - Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -437,17 +749,25 @@ async def register_inline( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.scripts.register_inline( - site_id="site_id", - source_code="alert('hello world');", - version="0.0.1", - display_name="Alert", - ) + + + async def main() -> None: + await client.scripts.register_inline( + site_id="580e63e98c9a982ac9b8b741", + source_code="alert('hello world');", + version="0.0.1", + display_name="Alert", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", @@ -459,22 +779,71 @@ async def register_inline( "version": version, "displayName": display_name, }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(CustomCodeInlineResponse, _response.json()) # type: ignore + return typing.cast( + CustomCodeInlineResponse, + parse_obj_as( + type_=CustomCodeInlineResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/sites/__init__.py b/src/webflow/resources/sites/__init__.py index c4ea3e7..3ec19db 100644 --- a/src/webflow/resources/sites/__init__.py +++ b/src/webflow/resources/sites/__init__.py @@ -1,5 +1,6 @@ # This file was auto-generated by Fern from our API Definition. -from .resources import activity_logs, scripts +from .types import SitesPublishResponse +from .resources import activity_logs, plans, redirects, scripts -__all__ = ["activity_logs", "scripts"] +__all__ = ["SitesPublishResponse", "activity_logs", "plans", "redirects", "scripts"] diff --git a/src/webflow/resources/sites/client.py b/src/webflow/resources/sites/client.py index 24b355d..c2a4468 100644 --- a/src/webflow/resources/sites/client.py +++ b/src/webflow/resources/sites/client.py @@ -1,24 +1,32 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from ...core.client_wrapper import SyncClientWrapper +from .resources.redirects.client import RedirectsClient +from .resources.plans.client import PlansClient +from .resources.activity_logs.client import ActivityLogsClient +from .resources.scripts.client import ScriptsClient from ...core.request_options import RequestOptions +from ...types.site import Site +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.forbidden_error import ForbiddenError -from ...errors.internal_server_error import InternalServerError from ...errors.not_found_error import NotFoundError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.domains import Domains -from ...types.site import Site +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError from ...types.sites import Sites -from .resources.activity_logs.client import ActivityLogsClient, AsyncActivityLogsClient -from .resources.scripts.client import AsyncScriptsClient, ScriptsClient +from ...types.domains import Domains +from .types.sites_publish_response import SitesPublishResponse +from ...core.client_wrapper import AsyncClientWrapper +from .resources.redirects.client import AsyncRedirectsClient +from .resources.plans.client import AsyncPlansClient +from .resources.activity_logs.client import AsyncActivityLogsClient +from .resources.scripts.client import AsyncScriptsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -27,12 +35,152 @@ class SitesClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper + self.redirects = RedirectsClient(client_wrapper=self._client_wrapper) + self.plans = PlansClient(client_wrapper=self._client_wrapper) self.activity_logs = ActivityLogsClient(client_wrapper=self._client_wrapper) self.scripts = ScriptsClient(client_wrapper=self._client_wrapper) + def create( + self, + workspace_id: str, + *, + name: str, + template_name: typing.Optional[str] = OMIT, + parent_folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Site: + """ + Create a site. This endpoint requires an Enterprise workspace. + + Required scope | `workspace:write` + + Parameters + ---------- + workspace_id : str + Unique identifier for a Workspace + + name : str + The name of the site + + template_name : typing.Optional[str] + The workspace or marketplace template to use + + parent_folder_id : typing.Optional[str] + MegaDodo Publications - Potential Book Ideas + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Site + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.create( + workspace_id="580e63e98c9a982ac9b8b741", + name="The Hitchhiker's Guide to the Galaxy", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"workspaces/{jsonable_encoder(workspace_id)}/sites", + method="POST", + json={ + "name": name, + "templateName": template_name, + "parentFolderId": parent_folder_id, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Sites: """ - List of all sites the provided access token is able to access.

Required scope | `sites:read` + List of all sites the provided access token is able to access. + + Required scope | `sites:read` Parameters ---------- @@ -46,27 +194,57 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Si Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.sites.list() """ - _response = self._client_wrapper.httpx_client.request("sites", method="GET", request_options=request_options) + _response = self._client_wrapper.httpx_client.request( + "sites", + method="GET", + request_options=request_options, + ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Sites, _response.json()) # type: ignore - if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + return typing.cast( + Sites, + parse_obj_as( + type_=Sites, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore - if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -74,7 +252,9 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Si def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Site: """ - Get a site by site id

Required scope | `sites:read` + Get details of a site. + + Required scope | `sites:read` Parameters ---------- @@ -91,31 +271,311 @@ def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.sites.get( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: + """ + Delete a site. This endpoint requires an Enterprise workspace. + + Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.delete( + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}", + method="DELETE", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Site, _response.json()) # type: ignore + return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update( + self, + site_id: str, + *, + name: typing.Optional[str] = OMIT, + parent_folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Site: + """ + Update a site. This endpoint requires an Enterprise workspace. + + Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + name : typing.Optional[str] + The name of the site + + parent_folder_id : typing.Optional[str] + The parent folder ID of the site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Site + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.update( + site_id="580e63e98c9a982ac9b8b741", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}", + method="PATCH", + json={ + "name": name, + "parentFolderId": parent_folder_id, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -123,7 +583,9 @@ def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] def get_custom_domain(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Domains: """ - Get a list of all custom domains related to site.

Required scope | `sites:read` + Get a list of all custom domains related to site. + + Required scope | `sites:read` Parameters ---------- @@ -140,31 +602,79 @@ def get_custom_domain(self, site_id: str, *, request_options: typing.Optional[Re Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.sites.get_custom_domain( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_domains", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/custom_domains", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Domains, _response.json()) # type: ignore + return typing.cast( + Domains, + parse_obj_as( + type_=Domains, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -177,9 +687,13 @@ def publish( custom_domains: typing.Optional[typing.Sequence[str]] = OMIT, publish_to_webflow_subdomain: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> None: + ) -> SitesPublishResponse: """ - Publish a site to one more more domains.

Required scope | `sites:write` + Publishes a site to one or more more domains. + + This endpoint has a limit of one successful publish queue per minute. + + Required scope | `sites:write` Parameters ---------- @@ -187,7 +701,7 @@ def publish( Unique identifier for a Site custom_domains : typing.Optional[typing.Sequence[str]] - Array of Custom Domain ids to publish + Array of Custom Domain IDs to publish publish_to_webflow_subdomain : typing.Optional[bool] Choice of whether to publish to the default Webflow Subdomain @@ -197,39 +711,92 @@ def publish( Returns ------- - None + SitesPublishResponse + Request accepted Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.sites.publish( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/publish", method="POST", - json={"customDomains": custom_domains, "publishToWebflowSubdomain": publish_to_webflow_subdomain}, + json={ + "customDomains": custom_domains, + "publishToWebflowSubdomain": publish_to_webflow_subdomain, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return + return typing.cast( + SitesPublishResponse, + parse_obj_as( + type_=SitesPublishResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -239,48 +806,232 @@ def publish( class AsyncSitesClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper + self.redirects = AsyncRedirectsClient(client_wrapper=self._client_wrapper) + self.plans = AsyncPlansClient(client_wrapper=self._client_wrapper) self.activity_logs = AsyncActivityLogsClient(client_wrapper=self._client_wrapper) self.scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) - async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Sites: + async def create( + self, + workspace_id: str, + *, + name: str, + template_name: typing.Optional[str] = OMIT, + parent_folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Site: """ - List of all sites the provided access token is able to access.

Required scope | `sites:read` + Create a site. This endpoint requires an Enterprise workspace. + + Required scope | `workspace:write` Parameters ---------- + workspace_id : str + Unique identifier for a Workspace + + name : str + The name of the site + + template_name : typing.Optional[str] + The workspace or marketplace template to use + + parent_folder_id : typing.Optional[str] + MegaDodo Publications - Potential Book Ideas + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - Sites + Site Request was successful Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.sites.list() + + + async def main() -> None: + await client.sites.create( + workspace_id="580e63e98c9a982ac9b8b741", + name="The Hitchhiker's Guide to the Galaxy", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - "sites", method="GET", request_options=request_options + f"workspaces/{jsonable_encoder(workspace_id)}/sites", + method="POST", + json={ + "name": name, + "templateName": template_name, + "parentFolderId": parent_folder_id, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Sites, _response.json()) # type: ignore + return typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Sites: + """ + List of all sites the provided access token is able to access. + + Required scope | `sites:read` + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Sites + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.list() + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "sites", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Sites, + parse_obj_as( + type_=Sites, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -288,7 +1039,9 @@ async def list(self, *, request_options: typing.Optional[RequestOptions] = None) async def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Site: """ - Get a site by site id

Required scope | `sites:read` + Get details of a site. + + Required scope | `sites:read` Parameters ---------- @@ -305,31 +1058,335 @@ async def get(self, site_id: str, *, request_options: typing.Optional[RequestOpt Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.get( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: + """ + Delete a site. This endpoint requires an Enterprise workspace. + + Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.sites.get( - site_id="site_id", + + + async def main() -> None: + await client.sites.delete( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}", + method="DELETE", + request_options=request_options, ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update( + self, + site_id: str, + *, + name: typing.Optional[str] = OMIT, + parent_folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Site: + """ + Update a site. This endpoint requires an Enterprise workspace. + + Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + name : typing.Optional[str] + The name of the site + + parent_folder_id : typing.Optional[str] + The parent folder ID of the site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Site + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.update( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}", + method="PATCH", + json={ + "name": name, + "parentFolderId": parent_folder_id, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Site, _response.json()) # type: ignore + return typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -339,7 +1396,9 @@ async def get_custom_domain( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> Domains: """ - Get a list of all custom domains related to site.

Required scope | `sites:read` + Get a list of all custom domains related to site. + + Required scope | `sites:read` Parameters ---------- @@ -356,31 +1415,87 @@ async def get_custom_domain( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.sites.get_custom_domain( - site_id="site_id", - ) + + + async def main() -> None: + await client.sites.get_custom_domain( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_domains", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/custom_domains", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Domains, _response.json()) # type: ignore + return typing.cast( + Domains, + parse_obj_as( + type_=Domains, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -393,9 +1508,13 @@ async def publish( custom_domains: typing.Optional[typing.Sequence[str]] = OMIT, publish_to_webflow_subdomain: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> None: + ) -> SitesPublishResponse: """ - Publish a site to one more more domains.

Required scope | `sites:write` + Publishes a site to one or more more domains. + + This endpoint has a limit of one successful publish queue per minute. + + Required scope | `sites:write` Parameters ---------- @@ -403,7 +1522,7 @@ async def publish( Unique identifier for a Site custom_domains : typing.Optional[typing.Sequence[str]] - Array of Custom Domain ids to publish + Array of Custom Domain IDs to publish publish_to_webflow_subdomain : typing.Optional[bool] Choice of whether to publish to the default Webflow Subdomain @@ -413,39 +1532,100 @@ async def publish( Returns ------- - None + SitesPublishResponse + Request accepted Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.sites.publish( - site_id="site_id", - ) + + + async def main() -> None: + await client.sites.publish( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/publish", method="POST", - json={"customDomains": custom_domains, "publishToWebflowSubdomain": publish_to_webflow_subdomain}, + json={ + "customDomains": custom_domains, + "publishToWebflowSubdomain": publish_to_webflow_subdomain, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return + return typing.cast( + SitesPublishResponse, + parse_obj_as( + type_=SitesPublishResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/sites/resources/__init__.py b/src/webflow/resources/sites/resources/__init__.py index b143a1f..1197a83 100644 --- a/src/webflow/resources/sites/resources/__init__.py +++ b/src/webflow/resources/sites/resources/__init__.py @@ -1,5 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from . import activity_logs, scripts +from . import activity_logs, plans, redirects, scripts -__all__ = ["activity_logs", "scripts"] +__all__ = ["activity_logs", "plans", "redirects", "scripts"] diff --git a/src/webflow/resources/sites/resources/activity_logs/client.py b/src/webflow/resources/sites/resources/activity_logs/client.py index 63571d4..cf4e1b3 100644 --- a/src/webflow/resources/sites/resources/activity_logs/client.py +++ b/src/webflow/resources/sites/resources/activity_logs/client.py @@ -1,18 +1,19 @@ # This file was auto-generated by Fern from our API Definition. +from .....core.client_wrapper import SyncClientWrapper import typing -from json.decoder import JSONDecodeError - -from .....core.api_error import ApiError -from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import pydantic_v1 from .....core.request_options import RequestOptions +from .....types.site_activity_log_response import SiteActivityLogResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as from .....errors.forbidden_error import ForbiddenError -from .....errors.internal_server_error import InternalServerError from .....errors.not_found_error import NotFoundError +from .....types.error import Error from .....errors.too_many_requests_error import TooManyRequestsError -from .....types.site_activity_log_response import SiteActivityLogResponse +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper class ActivityLogsClient: @@ -28,7 +29,7 @@ def list( request_options: typing.Optional[RequestOptions] = None, ) -> SiteActivityLogResponse: """ - Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` + Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` Parameters ---------- @@ -51,32 +52,73 @@ def list( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.sites.activity_logs.list( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/activity_logs", method="GET", - params={"limit": limit, "offset": offset}, + params={ + "limit": limit, + "offset": offset, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(SiteActivityLogResponse, _response.json()) # type: ignore + return typing.cast( + SiteActivityLogResponse, + parse_obj_as( + type_=SiteActivityLogResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -96,7 +138,7 @@ async def list( request_options: typing.Optional[RequestOptions] = None, ) -> SiteActivityLogResponse: """ - Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` + Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` Parameters ---------- @@ -119,32 +161,81 @@ async def list( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.sites.activity_logs.list( - site_id="site_id", - ) + + + async def main() -> None: + await client.sites.activity_logs.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/activity_logs", method="GET", - params={"limit": limit, "offset": offset}, + params={ + "limit": limit, + "offset": offset, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(SiteActivityLogResponse, _response.json()) # type: ignore + return typing.cast( + SiteActivityLogResponse, + parse_obj_as( + type_=SiteActivityLogResponse, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/types/missing_scopes.py b/src/webflow/resources/sites/resources/plans/__init__.py similarity index 57% rename from src/webflow/types/missing_scopes.py rename to src/webflow/resources/sites/resources/plans/__init__.py index a3b4b3e..f3ea265 100644 --- a/src/webflow/types/missing_scopes.py +++ b/src/webflow/resources/sites/resources/plans/__init__.py @@ -1,5 +1,2 @@ # This file was auto-generated by Fern from our API Definition. -from .error import Error - -MissingScopes = Error diff --git a/src/webflow/resources/sites/resources/plans/client.py b/src/webflow/resources/sites/resources/plans/client.py new file mode 100644 index 0000000..291231a --- /dev/null +++ b/src/webflow/resources/sites/resources/plans/client.py @@ -0,0 +1,233 @@ +# This file was auto-generated by Fern from our API Definition. + +from .....core.client_wrapper import SyncClientWrapper +import typing +from .....core.request_options import RequestOptions +from .....types.site_plan import SitePlan +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as +from .....errors.bad_request_error import BadRequestError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper + + +class PlansClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_site_plan(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> SitePlan: + """ + Get site plan details for the specified Site. + + Required scope | `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SitePlan + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.plans.get_site_plan( + site_id="580e63e98c9a982ac9b8b741", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/plan", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + SitePlan, + parse_obj_as( + type_=SitePlan, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncPlansClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_site_plan(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> SitePlan: + """ + Get site plan details for the specified Site. + + Required scope | `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SitePlan + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.plans.get_site_plan( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/plan", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + SitePlan, + parse_obj_as( + type_=SitePlan, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/webflow/resources/sites/resources/redirects/__init__.py b/src/webflow/resources/sites/resources/redirects/__init__.py new file mode 100644 index 0000000..f3ea265 --- /dev/null +++ b/src/webflow/resources/sites/resources/redirects/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/src/webflow/resources/sites/resources/redirects/client.py b/src/webflow/resources/sites/resources/redirects/client.py new file mode 100644 index 0000000..4bc0e7b --- /dev/null +++ b/src/webflow/resources/sites/resources/redirects/client.py @@ -0,0 +1,989 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .....core.client_wrapper import SyncClientWrapper +from .....core.request_options import RequestOptions +from .....types.redirects import Redirects +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as +from .....errors.bad_request_error import BadRequestError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .....types.redirect import Redirect +from .....core.client_wrapper import AsyncClientWrapper + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RedirectsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Redirects: + """ + Fetch a list of all URL redirect rules configured for a specific site. + + Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + + + Required scope: `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Redirects + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.redirects.list( + site_id="580e63e98c9a982ac9b8b741", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Redirects, + parse_obj_as( + type_=Redirects, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def create( + self, + site_id: str, + *, + id: typing.Optional[str] = OMIT, + from_url: typing.Optional[str] = OMIT, + to_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Redirect: + """ + Add a new URL redirection rule to a site. + + This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. + + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + id : typing.Optional[str] + The ID of the specific redirect rule + + from_url : typing.Optional[str] + The source URL path that will be redirected. + + to_url : typing.Optional[str] + The target URL path where the user or client will be redirected. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Redirect + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.redirects.create( + site_id="580e63e98c9a982ac9b8b741", + id="42e1a2b7aa1a13f768a0042a", + from_url="/mostly-harmless", + to_url="/earth", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects", + method="POST", + json={ + "id": id, + "fromUrl": from_url, + "toUrl": to_url, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Redirect, + parse_obj_as( + type_=Redirect, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete( + self, site_id: str, redirect_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> Redirects: + """ + Remove a URL redirection rule from a site. + This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + redirect_id : str + Unique identifier site rediect + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Redirects + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.redirects.delete( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Redirects, + parse_obj_as( + type_=Redirects, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update( + self, + site_id: str, + redirect_id: str, + *, + id: typing.Optional[str] = OMIT, + from_url: typing.Optional[str] = OMIT, + to_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Redirect: + """ + Update a URL redirection rule from a site. + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + redirect_id : str + Unique identifier site rediect + + id : typing.Optional[str] + The ID of the specific redirect rule + + from_url : typing.Optional[str] + The source URL path that will be redirected. + + to_url : typing.Optional[str] + The target URL path where the user or client will be redirected. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Redirect + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.redirects.update( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", + id="42e1a2b7aa1a13f768a0042a", + from_url="/mostly-harmless", + to_url="/earth", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + method="PATCH", + json={ + "id": id, + "fromUrl": from_url, + "toUrl": to_url, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Redirect, + parse_obj_as( + type_=Redirect, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncRedirectsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Redirects: + """ + Fetch a list of all URL redirect rules configured for a specific site. + + Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + + + Required scope: `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Redirects + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.redirects.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Redirects, + parse_obj_as( + type_=Redirects, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def create( + self, + site_id: str, + *, + id: typing.Optional[str] = OMIT, + from_url: typing.Optional[str] = OMIT, + to_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Redirect: + """ + Add a new URL redirection rule to a site. + + This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. + + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + id : typing.Optional[str] + The ID of the specific redirect rule + + from_url : typing.Optional[str] + The source URL path that will be redirected. + + to_url : typing.Optional[str] + The target URL path where the user or client will be redirected. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Redirect + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.redirects.create( + site_id="580e63e98c9a982ac9b8b741", + id="42e1a2b7aa1a13f768a0042a", + from_url="/mostly-harmless", + to_url="/earth", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects", + method="POST", + json={ + "id": id, + "fromUrl": from_url, + "toUrl": to_url, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Redirect, + parse_obj_as( + type_=Redirect, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete( + self, site_id: str, redirect_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> Redirects: + """ + Remove a URL redirection rule from a site. + This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + redirect_id : str + Unique identifier site rediect + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Redirects + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.redirects.delete( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Redirects, + parse_obj_as( + type_=Redirects, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update( + self, + site_id: str, + redirect_id: str, + *, + id: typing.Optional[str] = OMIT, + from_url: typing.Optional[str] = OMIT, + to_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Redirect: + """ + Update a URL redirection rule from a site. + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + redirect_id : str + Unique identifier site rediect + + id : typing.Optional[str] + The ID of the specific redirect rule + + from_url : typing.Optional[str] + The source URL path that will be redirected. + + to_url : typing.Optional[str] + The target URL path where the user or client will be redirected. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Redirect + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.redirects.update( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", + id="42e1a2b7aa1a13f768a0042a", + from_url="/mostly-harmless", + to_url="/earth", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + method="PATCH", + json={ + "id": id, + "fromUrl": from_url, + "toUrl": to_url, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Redirect, + parse_obj_as( + type_=Redirect, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/webflow/resources/sites/resources/scripts/client.py b/src/webflow/resources/sites/resources/scripts/client.py index 9470804..1954842 100644 --- a/src/webflow/resources/sites/resources/scripts/client.py +++ b/src/webflow/resources/sites/resources/scripts/client.py @@ -1,21 +1,23 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from .....core.api_error import ApiError -from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import pydantic_v1 +from .....core.client_wrapper import SyncClientWrapper from .....core.request_options import RequestOptions +from .....types.script_apply_list import ScriptApplyList +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as from .....errors.bad_request_error import BadRequestError -from .....errors.internal_server_error import InternalServerError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error from .....errors.not_found_error import NotFoundError from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.unauthorized_error import UnauthorizedError -from .....types.list_custom_code_blocks import ListCustomCodeBlocks +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError from .....types.script_apply import ScriptApply -from .....types.script_apply_list import ScriptApplyList +from .....core.serialization import convert_and_respect_annotation_metadata +from .....types.list_custom_code_blocks import ListCustomCodeBlocks +from .....core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -29,7 +31,11 @@ def get_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + Get all registered scripts that have been applied to a specific Site. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:read` Parameters ---------- @@ -46,31 +52,79 @@ def get_custom_code( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.sites.scripts.get_custom_code( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/custom_code", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + return typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -86,7 +140,15 @@ def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + Add a registered script to a Site. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -112,24 +174,23 @@ def upsert_custom_code( Examples -------- - from webflow import ScriptApply, ScriptApplyLocation - from webflow.client import Webflow + from webflow import ScriptApply, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.sites.scripts.upsert_custom_code( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", scripts=[ ScriptApply( id="cms_slider", - location=ScriptApplyLocation.HEADER, + location="header", version="1.0.0", attributes={"my-attribute": "some-value"}, ), ScriptApply( id="alert", - location=ScriptApplyLocation.HEADER, + location="header", version="0.0.1", ), ], @@ -138,23 +199,75 @@ def upsert_custom_code( _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", method="PUT", - json={"scripts": scripts, "lastUpdated": last_updated, "createdOn": created_on}, + json={ + "scripts": convert_and_respect_annotation_metadata( + object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" + ), + "lastUpdated": last_updated, + "createdOn": created_on, + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + return typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -162,7 +275,11 @@ def upsert_custom_code( def delete_custom_code(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete the custom code block that an app created for a Site

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + Delete the custom code block that an app created for a Site + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -178,31 +295,73 @@ def delete_custom_code(self, site_id: str, *, request_options: typing.Optional[R Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.sites.scripts.delete_custom_code( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code", method="DELETE", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/custom_code", + method="DELETE", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -217,7 +376,11 @@ def list_custom_code_blocks( request_options: typing.Optional[RequestOptions] = None, ) -> ListCustomCodeBlocks: """ - Get all instances of Custom Code applied to a Site or Pages.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + Get all instances of Custom Code applied to a Site or Pages. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:read` Parameters ---------- @@ -240,34 +403,83 @@ def list_custom_code_blocks( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.sites.scripts.list_custom_code_blocks( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", method="GET", - params={"offset": offset, "limit": limit}, + params={ + "offset": offset, + "limit": limit, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ListCustomCodeBlocks, _response.json()) # type: ignore + return typing.cast( + ListCustomCodeBlocks, + parse_obj_as( + type_=ListCustomCodeBlocks, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -282,7 +494,11 @@ async def get_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + Get all registered scripts that have been applied to a specific Site. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:read` Parameters ---------- @@ -299,31 +515,87 @@ async def get_custom_code( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.sites.scripts.get_custom_code( - site_id="site_id", - ) + + + async def main() -> None: + await client.sites.scripts.get_custom_code( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/custom_code", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + return typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -339,7 +611,15 @@ async def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Site.

In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate `custom_code` endpoints.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + Add a registered script to a Site. + + In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered + to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate + `custom_code` endpoints. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -365,49 +645,108 @@ async def upsert_custom_code( Examples -------- - from webflow import ScriptApply, ScriptApplyLocation - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow, ScriptApply client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.sites.scripts.upsert_custom_code( - site_id="site_id", - scripts=[ - ScriptApply( - id="cms_slider", - location=ScriptApplyLocation.HEADER, - version="1.0.0", - attributes={"my-attribute": "some-value"}, - ), - ScriptApply( - id="alert", - location=ScriptApplyLocation.HEADER, - version="0.0.1", - ), - ], - ) + + + async def main() -> None: + await client.sites.scripts.upsert_custom_code( + site_id="580e63e98c9a982ac9b8b741", + scripts=[ + ScriptApply( + id="cms_slider", + location="header", + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location="header", + version="0.0.1", + ), + ], + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", method="PUT", - json={"scripts": scripts, "lastUpdated": last_updated, "createdOn": created_on}, + json={ + "scripts": convert_and_respect_annotation_metadata( + object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" + ), + "lastUpdated": last_updated, + "createdOn": created_on, + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ScriptApplyList, _response.json()) # type: ignore + return typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -417,7 +756,11 @@ async def delete_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> None: """ - Delete the custom code block that an app created for a Site

Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:write` + Delete the custom code block that an app created for a Site + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:write` Parameters ---------- @@ -433,31 +776,81 @@ async def delete_custom_code( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.sites.scripts.delete_custom_code( - site_id="site_id", - ) + + + async def main() -> None: + await client.sites.scripts.delete_custom_code( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code", method="DELETE", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/custom_code", + method="DELETE", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -472,7 +865,11 @@ async def list_custom_code_blocks( request_options: typing.Optional[RequestOptions] = None, ) -> ListCustomCodeBlocks: """ - Get all instances of Custom Code applied to a Site or Pages.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `custom_code:read` + Get all instances of Custom Code applied to a Site or Pages. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Required scope | `custom_code:read` Parameters ---------- @@ -495,34 +892,91 @@ async def list_custom_code_blocks( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.sites.scripts.list_custom_code_blocks( - site_id="site_id", - ) + + + async def main() -> None: + await client.sites.scripts.list_custom_code_blocks( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", method="GET", - params={"offset": offset, "limit": limit}, + params={ + "offset": offset, + "limit": limit, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(ListCustomCodeBlocks, _response.json()) # type: ignore + return typing.cast( + ListCustomCodeBlocks, + parse_obj_as( + type_=ListCustomCodeBlocks, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/sites/types/__init__.py b/src/webflow/resources/sites/types/__init__.py new file mode 100644 index 0000000..c85fd30 --- /dev/null +++ b/src/webflow/resources/sites/types/__init__.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .sites_publish_response import SitesPublishResponse + +__all__ = ["SitesPublishResponse"] diff --git a/src/webflow/resources/sites/types/sites_publish_response.py b/src/webflow/resources/sites/types/sites_publish_response.py new file mode 100644 index 0000000..bf7a95b --- /dev/null +++ b/src/webflow/resources/sites/types/sites_publish_response.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....types.domain import Domain +from ....core.serialization import FieldMetadata +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SitesPublishResponse(UniversalBaseModel): + custom_domains: typing_extensions.Annotated[ + typing.Optional[typing.List[Domain]], FieldMetadata(alias="customDomains") + ] = pydantic.Field(default=None) + """ + Array of domains objects + """ + + publish_to_webflow_subdomain: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="publishToWebflowSubdomain") + ] = pydantic.Field(default=None) + """ + Flag for publishing to webflow.io subdomain + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/token/client.py b/src/webflow/resources/token/client.py index 19a9083..628ce3a 100644 --- a/src/webflow/resources/token/client.py +++ b/src/webflow/resources/token/client.py @@ -1,16 +1,17 @@ # This file was auto-generated by Fern from our API Definition. +from ...core.client_wrapper import SyncClientWrapper import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.pydantic_utilities import pydantic_v1 from ...core.request_options import RequestOptions -from ...errors.forbidden_error import ForbiddenError +from ...types.authorized_user import AuthorizedUser +from ...core.pydantic_utilities import parse_obj_as from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error +from ...errors.forbidden_error import ForbiddenError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError from ...types.authorization import Authorization -from ...types.authorized_user import AuthorizedUser +from ...core.client_wrapper import AsyncClientWrapper class TokenClient: @@ -19,7 +20,9 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = None) -> AuthorizedUser: """ - Information about the Authorized User

Required Scope | `authorized_user:read` + Information about the Authorized User + + Required Scope | `authorized_user:read` Parameters ---------- @@ -33,7 +36,7 @@ def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = No Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -41,15 +44,39 @@ def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = No client.token.authorized_by() """ _response = self._client_wrapper.httpx_client.request( - "token/authorized_by", method="GET", request_options=request_options + "token/authorized_by", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AuthorizedUser, _response.json()) # type: ignore + return typing.cast( + AuthorizedUser, + parse_obj_as( + type_=AuthorizedUser, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -57,7 +84,9 @@ def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = No def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) -> Authorization: """ - Information about the authorization token
Access to this endpoint requires a bearer token from a Data Client App.
+ Information about the authorization token + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). Parameters ---------- @@ -71,7 +100,7 @@ def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -79,13 +108,29 @@ def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) client.token.introspect() """ _response = self._client_wrapper.httpx_client.request( - "token/introspect", method="GET", request_options=request_options + "token/introspect", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Authorization, _response.json()) # type: ignore + return typing.cast( + Authorization, + parse_obj_as( + type_=Authorization, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -98,7 +143,9 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): async def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = None) -> AuthorizedUser: """ - Information about the Authorized User

Required Scope | `authorized_user:read` + Information about the Authorized User + + Required Scope | `authorized_user:read` Parameters ---------- @@ -112,23 +159,55 @@ async def authorized_by(self, *, request_options: typing.Optional[RequestOptions Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.token.authorized_by() + + + async def main() -> None: + await client.token.authorized_by() + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - "token/authorized_by", method="GET", request_options=request_options + "token/authorized_by", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(AuthorizedUser, _response.json()) # type: ignore + return typing.cast( + AuthorizedUser, + parse_obj_as( + type_=AuthorizedUser, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -136,7 +215,9 @@ async def authorized_by(self, *, request_options: typing.Optional[RequestOptions async def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) -> Authorization: """ - Information about the authorization token
Access to this endpoint requires a bearer token from a Data Client App.
+ Information about the authorization token + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). Parameters ---------- @@ -150,21 +231,45 @@ async def introspect(self, *, request_options: typing.Optional[RequestOptions] = Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.token.introspect() + + + async def main() -> None: + await client.token.introspect() + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - "token/introspect", method="GET", request_options=request_options + "token/introspect", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Authorization, _response.json()) # type: ignore + return typing.cast( + Authorization, + parse_obj_as( + type_=Authorization, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/users/client.py b/src/webflow/resources/users/client.py index 08e8045..d690c0f 100644 --- a/src/webflow/resources/users/client.py +++ b/src/webflow/resources/users/client.py @@ -1,24 +1,26 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from ...core.client_wrapper import SyncClientWrapper +from .types.users_list_request_sort import UsersListRequestSort from ...core.request_options import RequestOptions +from ...types.user_list import UserList +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError -from ...errors.conflict_error import ConflictError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.forbidden_error import ForbiddenError -from ...errors.internal_server_error import InternalServerError from ...errors.not_found_error import NotFoundError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError from ...types.user import User -from ...types.user_list import UserList -from .types.users_list_request_sort import UsersListRequestSort from .types.users_update_request_data import UsersUpdateRequestData +from ...core.serialization import convert_and_respect_annotation_metadata +from ...errors.conflict_error import ConflictError +from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -38,7 +40,9 @@ def list( request_options: typing.Optional[RequestOptions] = None, ) -> UserList: """ - Get a list of users for a site

Required scope | `users:read` + Get a list of users for a site + + Required scope | `users:read` Parameters ---------- @@ -68,36 +72,94 @@ def list( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.users.list( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users", method="GET", - params={"offset": offset, "limit": limit, "sort": sort}, + params={ + "offset": offset, + "limit": limit, + "sort": sort, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(UserList, _response.json()) # type: ignore + return typing.cast( + UserList, + parse_obj_as( + type_=UserList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -105,7 +167,9 @@ def list( def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> User: """ - Get a User by ID

Required scope | `users:read` + Get a User by ID + + Required scope | `users:read` Parameters ---------- @@ -125,14 +189,14 @@ def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[Re Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.users.get( - site_id="site_id", - user_id="user_id", + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( @@ -142,19 +206,73 @@ def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[Re ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + return typing.cast( + User, + parse_obj_as( + type_=User, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -162,7 +280,9 @@ def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[Re def delete(self, site_id: str, user_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete a User by ID

Required scope | `users:write` + Delete a User by ID + + Required scope | `users:write` Parameters ---------- @@ -181,14 +301,14 @@ def delete(self, site_id: str, user_id: str, *, request_options: typing.Optional Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.users.delete( - site_id="site_id", - user_id="user_id", + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( @@ -200,17 +320,65 @@ def delete(self, site_id: str, user_id: str, *, request_options: typing.Optional if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -226,9 +394,12 @@ def update( request_options: typing.Optional[RequestOptions] = None, ) -> User: """ - Update a User by ID

Required scope | `users:write` + Update a User by ID - + Required scope | `users:write` + + The email and password + fields cannot be updated using this endpoint Parameters ---------- @@ -254,15 +425,15 @@ def update( Examples -------- - from webflow import UsersUpdateRequestData - from webflow.client import Webflow + from webflow import Webflow + from webflow.resources.users import UsersUpdateRequestData client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.users.update( - site_id="site_id", - user_id="user_id", + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", data=UsersUpdateRequestData( name="Some One", accept_privacy=False, @@ -274,25 +445,87 @@ def update( _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", method="PATCH", - json={"data": data, "accessGroups": access_groups}, + json={ + "data": convert_and_respect_annotation_metadata( + object_=data, annotation=UsersUpdateRequestData, direction="write" + ), + "accessGroups": access_groups, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + return typing.cast( + User, + parse_obj_as( + type_=User, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -307,7 +540,11 @@ def invite( request_options: typing.Optional[RequestOptions] = None, ) -> User: """ - Create and invite a user with an email address. The user will be sent and invite via email, which they will need to accept in order to join paid Access Groups.

Required scope | `users:write` + Create and invite a user with an email address. + + The user will be sent and invite via email, which they will need to accept in order to join paid any paid access group. + + Required scope | `users:write` Parameters ---------- @@ -331,13 +568,13 @@ def invite( Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.users.invite( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", email="some.one@home.com", access_groups=["webflowers"], ) @@ -345,27 +582,95 @@ def invite( _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/invite", method="POST", - json={"email": email, "accessGroups": access_groups}, + json={ + "email": email, + "accessGroups": access_groups, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + return typing.cast( + User, + parse_obj_as( + type_=User, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -386,7 +691,9 @@ async def list( request_options: typing.Optional[RequestOptions] = None, ) -> UserList: """ - Get a list of users for a site

Required scope | `users:read` + Get a list of users for a site + + Required scope | `users:read` Parameters ---------- @@ -416,36 +723,102 @@ async def list( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.users.list( - site_id="site_id", - ) + + + async def main() -> None: + await client.users.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users", method="GET", - params={"offset": offset, "limit": limit, "sort": sort}, + params={ + "offset": offset, + "limit": limit, + "sort": sort, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(UserList, _response.json()) # type: ignore + return typing.cast( + UserList, + parse_obj_as( + type_=UserList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -453,7 +826,9 @@ async def list( async def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> User: """ - Get a User by ID

Required scope | `users:read` + Get a User by ID + + Required scope | `users:read` Parameters ---------- @@ -473,15 +848,23 @@ async def get(self, site_id: str, user_id: str, *, request_options: typing.Optio Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.users.get( - site_id="site_id", - user_id="user_id", - ) + + + async def main() -> None: + await client.users.get( + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", @@ -490,19 +873,73 @@ async def get(self, site_id: str, user_id: str, *, request_options: typing.Optio ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + return typing.cast( + User, + parse_obj_as( + type_=User, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -512,7 +949,9 @@ async def delete( self, site_id: str, user_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> None: """ - Delete a User by ID

Required scope | `users:write` + Delete a User by ID + + Required scope | `users:write` Parameters ---------- @@ -531,15 +970,23 @@ async def delete( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.users.delete( - site_id="site_id", - user_id="user_id", - ) + + + async def main() -> None: + await client.users.delete( + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", @@ -550,17 +997,65 @@ async def delete( if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -576,9 +1071,12 @@ async def update( request_options: typing.Optional[RequestOptions] = None, ) -> User: """ - Update a User by ID

Required scope | `users:write` + Update a User by ID + + Required scope | `users:write` - + The email and password + fields cannot be updated using this endpoint Parameters ---------- @@ -604,45 +1102,115 @@ async def update( Examples -------- - from webflow import UsersUpdateRequestData - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow + from webflow.resources.users import UsersUpdateRequestData client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.users.update( - site_id="site_id", - user_id="user_id", - data=UsersUpdateRequestData( - name="Some One", - accept_privacy=False, - accept_communications=False, - ), - access_groups=["webflowers", "platinum", "free-tier"], - ) + + + async def main() -> None: + await client.users.update( + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", + data=UsersUpdateRequestData( + name="Some One", + accept_privacy=False, + accept_communications=False, + ), + access_groups=["webflowers", "platinum", "free-tier"], + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", method="PATCH", - json={"data": data, "accessGroups": access_groups}, + json={ + "data": convert_and_respect_annotation_metadata( + object_=data, annotation=UsersUpdateRequestData, direction="write" + ), + "accessGroups": access_groups, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + return typing.cast( + User, + parse_obj_as( + type_=User, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -657,7 +1225,11 @@ async def invite( request_options: typing.Optional[RequestOptions] = None, ) -> User: """ - Create and invite a user with an email address. The user will be sent and invite via email, which they will need to accept in order to join paid Access Groups.

Required scope | `users:write` + Create and invite a user with an email address. + + The user will be sent and invite via email, which they will need to accept in order to join paid any paid access group. + + Required scope | `users:write` Parameters ---------- @@ -681,41 +1253,117 @@ async def invite( Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.users.invite( - site_id="site_id", - email="some.one@home.com", - access_groups=["webflowers"], - ) + + + async def main() -> None: + await client.users.invite( + site_id="580e63e98c9a982ac9b8b741", + email="some.one@home.com", + access_groups=["webflowers"], + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/users/invite", method="POST", - json={"email": email, "accessGroups": access_groups}, + json={ + "email": email, + "accessGroups": access_groups, + }, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(User, _response.json()) # type: ignore + return typing.cast( + User, + parse_obj_as( + type_=User, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 403: - raise ForbiddenError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 409: - raise ConflictError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/resources/users/types/users_list_request_sort.py b/src/webflow/resources/users/types/users_list_request_sort.py index abd1e99..e4143a4 100644 --- a/src/webflow/resources/users/types/users_list_request_sort.py +++ b/src/webflow/resources/users/types/users_list_request_sort.py @@ -1,92 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class UsersListRequestSort(str, enum.Enum): - CREATED_ON_ASCENDING = "CreatedOn" - """ - Sorts users in ascending order based on their created date - """ - - CREATED_ON_DESCENDING = "-CreatedOn" - """ - Sorts users in descending order based on their created date - """ - - EMAIL_ASCENDING = "Email" - """ - Sorts users in ascending order based on their email - """ - - EMAIL_DESCENDING = "-Email" - """ - Sorts users in descending order based on their email - """ - - STATUS_ASCENDING = "Status" - """ - Sorts users in ascending order based on their status - """ - - STATUS_DESCENDING = "-Status" - """ - Sorts users in descending order based on their status - """ - - LAST_LOGIN_ASCENDING = "LastLogin" - """ - Sorts users in ascending order based on their last login date - """ - - LAST_LOGIN_DESCENDING = "-LastLogin" - """ - Sorts users in descending order based on their last login date - """ - - UPDATED_ON_ASCENDING = "UpdatedOn" - """ - Sorts users in ascending order based on their update date - """ - - UPDATED_ON_DESCENDING = "-UpdatedOn" - """ - Sorts users in descending order based on their update date - """ - - def visit( - self, - created_on_ascending: typing.Callable[[], T_Result], - created_on_descending: typing.Callable[[], T_Result], - email_ascending: typing.Callable[[], T_Result], - email_descending: typing.Callable[[], T_Result], - status_ascending: typing.Callable[[], T_Result], - status_descending: typing.Callable[[], T_Result], - last_login_ascending: typing.Callable[[], T_Result], - last_login_descending: typing.Callable[[], T_Result], - updated_on_ascending: typing.Callable[[], T_Result], - updated_on_descending: typing.Callable[[], T_Result], - ) -> T_Result: - if self is UsersListRequestSort.CREATED_ON_ASCENDING: - return created_on_ascending() - if self is UsersListRequestSort.CREATED_ON_DESCENDING: - return created_on_descending() - if self is UsersListRequestSort.EMAIL_ASCENDING: - return email_ascending() - if self is UsersListRequestSort.EMAIL_DESCENDING: - return email_descending() - if self is UsersListRequestSort.STATUS_ASCENDING: - return status_ascending() - if self is UsersListRequestSort.STATUS_DESCENDING: - return status_descending() - if self is UsersListRequestSort.LAST_LOGIN_ASCENDING: - return last_login_ascending() - if self is UsersListRequestSort.LAST_LOGIN_DESCENDING: - return last_login_descending() - if self is UsersListRequestSort.UPDATED_ON_ASCENDING: - return updated_on_ascending() - if self is UsersListRequestSort.UPDATED_ON_DESCENDING: - return updated_on_descending() +UsersListRequestSort = typing.Union[ + typing.Literal[ + "CreatedOn", + "-CreatedOn", + "Email", + "-Email", + "Status", + "-Status", + "LastLogin", + "-LastLogin", + "UpdatedOn", + "-UpdatedOn", + ], + typing.Any, +] diff --git a/src/webflow/resources/users/types/users_update_request_data.py b/src/webflow/resources/users/types/users_update_request_data.py index c765cea..919406c 100644 --- a/src/webflow/resources/users/types/users_update_request_data.py +++ b/src/webflow/resources/users/types/users_update_request_data.py @@ -1,44 +1,38 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ....core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +import typing_extensions +from ....core.serialization import FieldMetadata +from ....core.pydantic_utilities import IS_PYDANTIC_V2 -from ....core.datetime_utils import serialize_datetime -from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class UsersUpdateRequestData(pydantic_v1.BaseModel): - name: typing.Optional[str] = pydantic_v1.Field(default=None) +class UsersUpdateRequestData(UniversalBaseModel): + name: typing.Optional[str] = pydantic.Field(default=None) """ The name of the user """ - accept_privacy: typing.Optional[bool] = pydantic_v1.Field(alias="accept-privacy", default=None) + accept_privacy: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="accept-privacy")] = ( + pydantic.Field(default=None) + ) """ Boolean indicating if the user has accepted the privacy policy """ - accept_communications: typing.Optional[bool] = pydantic_v1.Field(alias="accept-communications", default=None) + accept_communications: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="accept-communications") + ] = pydantic.Field(default=None) """ Boolean indicating if the user has accepted to receive communications """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/webhooks/client.py b/src/webflow/resources/webhooks/client.py index 9225c18..ded9a2f 100644 --- a/src/webflow/resources/webhooks/client.py +++ b/src/webflow/resources/webhooks/client.py @@ -1,21 +1,25 @@ # This file was auto-generated by Fern from our API Definition. import typing -from json.decoder import JSONDecodeError - -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import pydantic_v1 +from ...core.client_wrapper import SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.webhook_list import WebhookList +from ...core.jsonable_encoder import jsonable_encoder +from ...core.pydantic_utilities import parse_obj_as from ...errors.bad_request_error import BadRequestError -from ...errors.internal_server_error import InternalServerError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error from ...errors.not_found_error import NotFoundError from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.unauthorized_error import UnauthorizedError +from ...errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from ...core.api_error import ApiError from ...types.trigger_type import TriggerType +from ...types.webhook_filter import WebhookFilter +import datetime as dt from ...types.webhook import Webhook -from ...types.webhook_list import WebhookList +from ...core.serialization import convert_and_respect_annotation_metadata +from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -27,7 +31,9 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> WebhookList: """ - List all App-created Webhooks registered for a given site

Required scope | `sites:read` + List all App-created Webhooks registered for a given site + + Required scope | `sites:read` Parameters ---------- @@ -44,31 +50,79 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.webhooks.list( - site_id="site_id", + site_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/webhooks", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/webhooks", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(WebhookList, _response.json()) # type: ignore + return typing.cast( + WebhookList, + parse_obj_as( + type_=WebhookList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -76,31 +130,53 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] def create( self, - site_id: str, + site_id_: str, *, - trigger_type: TriggerType, - url: str, - filter: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + id: typing.Optional[str] = OMIT, + trigger_type: typing.Optional[TriggerType] = OMIT, + url: typing.Optional[str] = OMIT, + workspace_id: typing.Optional[str] = OMIT, + site_id: typing.Optional[str] = OMIT, + filter: typing.Optional[WebhookFilter] = OMIT, + last_triggered: typing.Optional[dt.datetime] = OMIT, + created_on: typing.Optional[dt.datetime] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Webhook: """ - Create a new Webhook, to be notified when Webflow resources change. Limit of 75 registrations per `triggerType`, per site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `sites:write` + Create a new Webhook. + + Limit of 75 registrations per `triggerType`, per site. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Required scope | `sites:write` Parameters ---------- - site_id : str + site_id_ : str Unique identifier for a Site - trigger_type : TriggerType + id : typing.Optional[str] + Unique identifier for the Webhook registration + + trigger_type : typing.Optional[TriggerType] - url : str - The server URI that Webflow will call when your Webhook is triggered + url : typing.Optional[str] + URL to send the Webhook payload to + workspace_id : typing.Optional[str] + Unique identifier for the Workspace the Webhook is registered in - filter : typing.Optional[typing.Dict[str, typing.Any]] - Filter for selecting which events you want Webhooks to be triggered for. - ** Only available for `form_submission` trigger types. ** + site_id : typing.Optional[str] + Unique identifier for the Site the Webhook is registered in + filter : typing.Optional[WebhookFilter] + Only supported for the `form_submission` trigger type. Filter for the form you want Webhooks to be sent for. + + last_triggered : typing.Optional[dt.datetime] + Date the Webhook instance was last triggered + + created_on : typing.Optional[dt.datetime] + Date the Webhook registration was created request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -112,38 +188,105 @@ def create( Examples -------- - from webflow import TriggerType - from webflow.client import Webflow + import datetime + + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.webhooks.create( - site_id="site_id", - trigger_type=TriggerType.FORM_SUBMISSION, - url="https://api.mydomain.com/webhook", + site_id_="580e63e98c9a982ac9b8b741", + id="582266e0cd48de0f0e3c6d8b", + trigger_type="form_submission", + url="https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", + workspace_id="4f4e46fd476ea8c507000001", + site_id="562ac0395358780a1f5e6fbd", + last_triggered=datetime.datetime.fromisoformat( + "2023-02-08 23:59:28+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2022-11-08 23:59:28+00:00", + ), ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/webhooks", + f"sites/{jsonable_encoder(site_id_)}/webhooks", method="POST", - json={"triggerType": trigger_type, "url": url, "filter": filter}, + json={ + "id": id, + "triggerType": trigger_type, + "url": url, + "workspaceId": workspace_id, + "siteId": site_id, + "filter": convert_and_respect_annotation_metadata( + object_=filter, annotation=WebhookFilter, direction="write" + ), + "lastTriggered": last_triggered, + "createdOn": created_on, + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Webhook, _response.json()) # type: ignore + return typing.cast( + Webhook, + parse_obj_as( + type_=Webhook, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -153,6 +296,8 @@ def get(self, webhook_id: str, *, request_options: typing.Optional[RequestOption """ Get a specific Webhook instance + Required scope: `sites:read` + Parameters ---------- webhook_id : str @@ -168,31 +313,79 @@ def get(self, webhook_id: str, *, request_options: typing.Optional[RequestOption Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.webhooks.get( - webhook_id="webhook_id", + webhook_id="580e64008c9a982ac9b8b754", ) """ _response = self._client_wrapper.httpx_client.request( - f"webhooks/{jsonable_encoder(webhook_id)}", method="GET", request_options=request_options + f"webhooks/{jsonable_encoder(webhook_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Webhook, _response.json()) # type: ignore + return typing.cast( + Webhook, + parse_obj_as( + type_=Webhook, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -202,6 +395,8 @@ def delete(self, webhook_id: str, *, request_options: typing.Optional[RequestOpt """ Remove a Webhook + Required scope: `sites:read` + Parameters ---------- webhook_id : str @@ -216,31 +411,73 @@ def delete(self, webhook_id: str, *, request_options: typing.Optional[RequestOpt Examples -------- - from webflow.client import Webflow + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.webhooks.delete( - webhook_id="webhook_id", + webhook_id="580e64008c9a982ac9b8b754", ) """ _response = self._client_wrapper.httpx_client.request( - f"webhooks/{jsonable_encoder(webhook_id)}", method="DELETE", request_options=request_options + f"webhooks/{jsonable_encoder(webhook_id)}", + method="DELETE", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -253,7 +490,9 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): async def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> WebhookList: """ - List all App-created Webhooks registered for a given site

Required scope | `sites:read` + List all App-created Webhooks registered for a given site + + Required scope | `sites:read` Parameters ---------- @@ -270,31 +509,87 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.webhooks.list( - site_id="site_id", - ) + + + async def main() -> None: + await client.webhooks.list( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/webhooks", method="GET", request_options=request_options + f"sites/{jsonable_encoder(site_id)}/webhooks", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(WebhookList, _response.json()) # type: ignore + return typing.cast( + WebhookList, + parse_obj_as( + type_=WebhookList, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -302,31 +597,53 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp async def create( self, - site_id: str, + site_id_: str, *, - trigger_type: TriggerType, - url: str, - filter: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + id: typing.Optional[str] = OMIT, + trigger_type: typing.Optional[TriggerType] = OMIT, + url: typing.Optional[str] = OMIT, + workspace_id: typing.Optional[str] = OMIT, + site_id: typing.Optional[str] = OMIT, + filter: typing.Optional[WebhookFilter] = OMIT, + last_triggered: typing.Optional[dt.datetime] = OMIT, + created_on: typing.Optional[dt.datetime] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Webhook: """ - Create a new Webhook, to be notified when Webflow resources change. Limit of 75 registrations per `triggerType`, per site.
Access to this endpoint requires a bearer token from a Data Client App.
Required scope | `sites:write` + Create a new Webhook. + + Limit of 75 registrations per `triggerType`, per site. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Required scope | `sites:write` Parameters ---------- - site_id : str + site_id_ : str Unique identifier for a Site - trigger_type : TriggerType + id : typing.Optional[str] + Unique identifier for the Webhook registration - url : str - The server URI that Webflow will call when your Webhook is triggered + trigger_type : typing.Optional[TriggerType] + url : typing.Optional[str] + URL to send the Webhook payload to - filter : typing.Optional[typing.Dict[str, typing.Any]] - Filter for selecting which events you want Webhooks to be triggered for. - ** Only available for `form_submission` trigger types. ** + workspace_id : typing.Optional[str] + Unique identifier for the Workspace the Webhook is registered in + site_id : typing.Optional[str] + Unique identifier for the Site the Webhook is registered in + + filter : typing.Optional[WebhookFilter] + Only supported for the `form_submission` trigger type. Filter for the form you want Webhooks to be sent for. + + last_triggered : typing.Optional[dt.datetime] + Date the Webhook instance was last triggered + + created_on : typing.Optional[dt.datetime] + Date the Webhook registration was created request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -338,38 +655,112 @@ async def create( Examples -------- - from webflow import TriggerType - from webflow.client import AsyncWebflow + import asyncio + import datetime + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.webhooks.create( - site_id="site_id", - trigger_type=TriggerType.FORM_SUBMISSION, - url="https://api.mydomain.com/webhook", - ) + + + async def main() -> None: + await client.webhooks.create( + site_id_="580e63e98c9a982ac9b8b741", + id="582266e0cd48de0f0e3c6d8b", + trigger_type="form_submission", + url="https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", + workspace_id="4f4e46fd476ea8c507000001", + site_id="562ac0395358780a1f5e6fbd", + last_triggered=datetime.datetime.fromisoformat( + "2023-02-08 23:59:28+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2022-11-08 23:59:28+00:00", + ), + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/webhooks", + f"sites/{jsonable_encoder(site_id_)}/webhooks", method="POST", - json={"triggerType": trigger_type, "url": url, "filter": filter}, + json={ + "id": id, + "triggerType": trigger_type, + "url": url, + "workspaceId": workspace_id, + "siteId": site_id, + "filter": convert_and_respect_annotation_metadata( + object_=filter, annotation=WebhookFilter, direction="write" + ), + "lastTriggered": last_triggered, + "createdOn": created_on, + }, request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Webhook, _response.json()) # type: ignore + return typing.cast( + Webhook, + parse_obj_as( + type_=Webhook, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -379,6 +770,8 @@ async def get(self, webhook_id: str, *, request_options: typing.Optional[Request """ Get a specific Webhook instance + Required scope: `sites:read` + Parameters ---------- webhook_id : str @@ -394,31 +787,87 @@ async def get(self, webhook_id: str, *, request_options: typing.Optional[Request Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.webhooks.get( - webhook_id="webhook_id", - ) + + + async def main() -> None: + await client.webhooks.get( + webhook_id="580e64008c9a982ac9b8b754", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"webhooks/{jsonable_encoder(webhook_id)}", method="GET", request_options=request_options + f"webhooks/{jsonable_encoder(webhook_id)}", + method="GET", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return pydantic_v1.parse_obj_as(Webhook, _response.json()) # type: ignore + return typing.cast( + Webhook, + parse_obj_as( + type_=Webhook, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) @@ -428,6 +877,8 @@ async def delete(self, webhook_id: str, *, request_options: typing.Optional[Requ """ Remove a Webhook + Required scope: `sites:read` + Parameters ---------- webhook_id : str @@ -442,31 +893,81 @@ async def delete(self, webhook_id: str, *, request_options: typing.Optional[Requ Examples -------- - from webflow.client import AsyncWebflow + import asyncio + + from webflow import AsyncWebflow client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", ) - await client.webhooks.delete( - webhook_id="webhook_id", - ) + + + async def main() -> None: + await client.webhooks.delete( + webhook_id="580e64008c9a982ac9b8b754", + ) + + + asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"webhooks/{jsonable_encoder(webhook_id)}", method="DELETE", request_options=request_options + f"webhooks/{jsonable_encoder(webhook_id)}", + method="DELETE", + request_options=request_options, ) try: if 200 <= _response.status_code < 300: return if _response.status_code == 400: - raise BadRequestError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 401: - raise UnauthorizedError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 404: - raise NotFoundError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: - raise TooManyRequestsError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 500: - raise InternalServerError(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) _response_json = _response.json() except JSONDecodeError: raise ApiError(status_code=_response.status_code, body=_response.text) diff --git a/src/webflow/types/__init__.py b/src/webflow/types/__init__.py index 16b5e7c..5b2d8c6 100644 --- a/src/webflow/types/__init__.py +++ b/src/webflow/types/__init__.py @@ -15,13 +15,33 @@ from .authorization_authorization_authorized_to import AuthorizationAuthorizationAuthorizedTo from .authorized_user import AuthorizedUser from .bad_request_error_body import BadRequestErrorBody +from .bulk_collection_item import BulkCollectionItem +from .bulk_collection_item_field_data import BulkCollectionItemFieldData from .collection import Collection from .collection_item import CollectionItem from .collection_item_field_data import CollectionItemFieldData from .collection_item_list import CollectionItemList +from .collection_item_list_no_pagination import CollectionItemListNoPagination from .collection_item_list_pagination import CollectionItemListPagination +from .collection_item_patch_single import CollectionItemPatchSingle +from .collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData +from .collection_item_post_single import CollectionItemPostSingle +from .collection_item_post_single_field_data import CollectionItemPostSingleFieldData +from .collection_item_with_id_input import CollectionItemWithIdInput +from .collection_item_with_id_input_field_data import CollectionItemWithIdInputFieldData from .collection_list import CollectionList from .collection_list_array_item import CollectionListArrayItem +from .component import Component +from .component_dom import ComponentDom +from .component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite +from .component_instance_node_property_overrides_write_property_overrides_item import ( + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, +) +from .component_list import ComponentList +from .component_node import ComponentNode +from .component_properties import ComponentProperties +from .component_property import ComponentProperty +from .component_property_type import ComponentPropertyType from .conflict_error_body import ConflictErrorBody from .custom_code_block import CustomCodeBlock from .custom_code_block_type import CustomCodeBlockType @@ -33,7 +53,7 @@ from .duplicate_user_email import DuplicateUserEmail from .ecommerce_settings import EcommerceSettings from .error import Error -from .error_details_item import ErrorDetailsItem +from .error_code import ErrorCode from .field import Field from .field_type import FieldType from .forbidden_error_body import ForbiddenErrorBody @@ -46,18 +66,18 @@ from .form_submission import FormSubmission from .form_submission_list import FormSubmissionList from .image_node import ImageNode +from .image_node_image import ImageNodeImage from .invalid_domain import InvalidDomain +from .invalid_scopes import InvalidScopes from .inventory_item import InventoryItem from .inventory_item_inventory_type import InventoryItemInventoryType from .list_custom_code_blocks import ListCustomCodeBlocks from .locale import Locale from .locales import Locales -from .missing_scopes import MissingScopes from .no_domains import NoDomains -from .node import Node -from .node_type import NodeType +from .node import Node, Node_ComponentInstance, Node_Image, Node_Text from .not_enterprise_plan_site import NotEnterprisePlanSite -from .oauth_scope import OauthScope +from .not_enterprise_plan_workspace import NotEnterprisePlanWorkspace from .order import Order from .order_address import OrderAddress from .order_address_japan_type import OrderAddressJapanType @@ -77,9 +97,6 @@ from .order_totals_extras_item import OrderTotalsExtrasItem from .order_totals_extras_item_type import OrderTotalsExtrasItemType from .page import Page -from .page_details import PageDetails -from .page_details_open_graph import PageDetailsOpenGraph -from .page_details_seo import PageDetailsSeo from .page_list import PageList from .page_open_graph import PageOpenGraph from .page_seo import PageSeo @@ -92,6 +109,8 @@ from .product_field_data_ec_product_type import ProductFieldDataEcProductType from .product_field_data_tax_category import ProductFieldDataTaxCategory from .publish_status import PublishStatus +from .redirect import Redirect +from .redirects import Redirects from .registered_script_list import RegisteredScriptList from .script_apply import ScriptApply from .script_apply_list import ScriptApplyList @@ -99,9 +118,14 @@ from .scripts import Scripts from .site import Site from .site_activity_log_item import SiteActivityLogItem +from .site_activity_log_item_event import SiteActivityLogItemEvent from .site_activity_log_item_resource_operation import SiteActivityLogItemResourceOperation from .site_activity_log_item_user import SiteActivityLogItemUser from .site_activity_log_response import SiteActivityLogResponse +from .site_data_collection_type import SiteDataCollectionType +from .site_plan import SitePlan +from .site_plan_id import SitePlanId +from .site_plan_name import SitePlanName from .sites import Sites from .sku import Sku from .sku_field_data import SkuFieldData @@ -119,7 +143,10 @@ from .stripe_card_brand import StripeCardBrand from .stripe_card_expires import StripeCardExpires from .stripe_details import StripeDetails +from .text import Text from .text_node import TextNode +from .text_node_text import TextNodeText +from .text_node_write import TextNodeWrite from .trigger_type import TriggerType from .user import User from .user_access_groups_item import UserAccessGroupsItem @@ -131,6 +158,7 @@ from .user_status import UserStatus from .users_not_enabled import UsersNotEnabled from .webhook import Webhook +from .webhook_filter import WebhookFilter from .webhook_list import WebhookList __all__ = [ @@ -149,13 +177,31 @@ "AuthorizationAuthorizationAuthorizedTo", "AuthorizedUser", "BadRequestErrorBody", + "BulkCollectionItem", + "BulkCollectionItemFieldData", "Collection", "CollectionItem", "CollectionItemFieldData", "CollectionItemList", + "CollectionItemListNoPagination", "CollectionItemListPagination", + "CollectionItemPatchSingle", + "CollectionItemPatchSingleFieldData", + "CollectionItemPostSingle", + "CollectionItemPostSingleFieldData", + "CollectionItemWithIdInput", + "CollectionItemWithIdInputFieldData", "CollectionList", "CollectionListArrayItem", + "Component", + "ComponentDom", + "ComponentInstanceNodePropertyOverridesWrite", + "ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem", + "ComponentList", + "ComponentNode", + "ComponentProperties", + "ComponentProperty", + "ComponentPropertyType", "ConflictErrorBody", "CustomCodeBlock", "CustomCodeBlockType", @@ -167,7 +213,7 @@ "DuplicateUserEmail", "EcommerceSettings", "Error", - "ErrorDetailsItem", + "ErrorCode", "Field", "FieldType", "ForbiddenErrorBody", @@ -180,18 +226,21 @@ "FormSubmission", "FormSubmissionList", "ImageNode", + "ImageNodeImage", "InvalidDomain", + "InvalidScopes", "InventoryItem", "InventoryItemInventoryType", "ListCustomCodeBlocks", "Locale", "Locales", - "MissingScopes", "NoDomains", "Node", - "NodeType", + "Node_ComponentInstance", + "Node_Image", + "Node_Text", "NotEnterprisePlanSite", - "OauthScope", + "NotEnterprisePlanWorkspace", "Order", "OrderAddress", "OrderAddressJapanType", @@ -211,9 +260,6 @@ "OrderTotalsExtrasItem", "OrderTotalsExtrasItemType", "Page", - "PageDetails", - "PageDetailsOpenGraph", - "PageDetailsSeo", "PageList", "PageOpenGraph", "PageSeo", @@ -226,6 +272,8 @@ "ProductFieldDataEcProductType", "ProductFieldDataTaxCategory", "PublishStatus", + "Redirect", + "Redirects", "RegisteredScriptList", "ScriptApply", "ScriptApplyList", @@ -233,9 +281,14 @@ "Scripts", "Site", "SiteActivityLogItem", + "SiteActivityLogItemEvent", "SiteActivityLogItemResourceOperation", "SiteActivityLogItemUser", "SiteActivityLogResponse", + "SiteDataCollectionType", + "SitePlan", + "SitePlanId", + "SitePlanName", "Sites", "Sku", "SkuFieldData", @@ -253,7 +306,10 @@ "StripeCardBrand", "StripeCardExpires", "StripeDetails", + "Text", "TextNode", + "TextNodeText", + "TextNodeWrite", "TriggerType", "User", "UserAccessGroupsItem", @@ -265,5 +321,6 @@ "UserStatus", "UsersNotEnabled", "Webhook", + "WebhookFilter", "WebhookList", ] diff --git a/src/webflow/types/access_group.py b/src/webflow/types/access_group.py index d0b56f3..fa2a418 100644 --- a/src/webflow/types/access_group.py +++ b/src/webflow/types/access_group.py @@ -1,54 +1,49 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class AccessGroup(pydantic_v1.BaseModel): - id: typing.Optional[str] = pydantic_v1.Field(default=None) +class AccessGroup(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for the Access Group """ - name: typing.Optional[str] = pydantic_v1.Field(default=None) + name: typing.Optional[str] = pydantic.Field(default=None) """ Name of the the Access Group """ - short_id: typing.Optional[str] = pydantic_v1.Field(alias="shortId", default=None) + short_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="shortId")] = pydantic.Field( + default=None + ) """ Shortened unique identifier based on name, optimized for its use in the user’s JWT """ - slug: typing.Optional[str] = pydantic_v1.Field(default=None) + slug: typing.Optional[str] = pydantic.Field(default=None) """ Shortened unique identifier based on name, optimized for human readability and public API use """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ The date the Access Group was created """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/access_group_list.py b/src/webflow/types/access_group_list.py index a215c84..0d5e140 100644 --- a/src/webflow/types/access_group_list.py +++ b/src/webflow/types/access_group_list.py @@ -1,59 +1,51 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions from .access_group import AccessGroup +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class AccessGroupList(pydantic_v1.BaseModel): +class AccessGroupList(UniversalBaseModel): """ The list access groups results """ - count: typing.Optional[float] = pydantic_v1.Field(default=None) + count: typing.Optional[float] = pydantic.Field(default=None) """ Number of access groups returned """ - limit: typing.Optional[float] = pydantic_v1.Field(default=None) + limit: typing.Optional[float] = pydantic.Field(default=None) """ The limit specified in the request """ - offset: typing.Optional[float] = pydantic_v1.Field(default=None) + offset: typing.Optional[float] = pydantic.Field(default=None) """ The offset specified for pagination """ - total: typing.Optional[float] = pydantic_v1.Field(default=None) + total: typing.Optional[float] = pydantic.Field(default=None) """ Total number of access groups in the collection """ - access_groups: typing.Optional[typing.List[AccessGroup]] = pydantic_v1.Field(alias="accessGroups", default=None) + access_groups: typing_extensions.Annotated[ + typing.Optional[typing.List[AccessGroup]], FieldMetadata(alias="accessGroups") + ] = pydantic.Field(default=None) """ List of Site Access Groups """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/application.py b/src/webflow/types/application.py index bdfe171..ac819f0 100644 --- a/src/webflow/types/application.py +++ b/src/webflow/types/application.py @@ -2,4 +2,4 @@ import typing -Application = typing.Any +Application = typing.Optional[typing.Any] diff --git a/src/webflow/types/asset.py b/src/webflow/types/asset.py index d76f5ed..b67cefa 100644 --- a/src/webflow/types/asset.py +++ b/src/webflow/types/asset.py @@ -1,77 +1,88 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt from .asset_variant import AssetVariant +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Asset(pydantic_v1.BaseModel): - id: typing.Optional[str] = pydantic_v1.Field(default=None) +class Asset(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for this asset """ - original_file_name: typing.Optional[str] = pydantic_v1.Field(alias="originalFileName", default=None) + content_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="contentType")] = ( + pydantic.Field(default=None) + ) """ - Original file name at the time of upload + File format type """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + size: typing.Optional[int] = pydantic.Field(default=None) """ - Display name of the asset + size in bytes """ - content_type: typing.Optional[str] = pydantic_v1.Field(alias="contentType", default=None) + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) """ - File format type + Unique identifier for the site that hosts this asset """ - size: typing.Optional[int] = pydantic_v1.Field(default=None) + hosted_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="hostedUrl")] = pydantic.Field( + default=None + ) """ - size in bytes + Link to the asset """ - site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + original_file_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="originalFileName")] = ( + pydantic.Field(default=None) + ) """ - Unique identifier for the site that hosts this asset + Original file name at the time of upload """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ - Date the asset metadata was created + Display name of the asset """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ Date the asset metadata was last updated """ - hosted_url: typing.Optional[str] = pydantic_v1.Field(alias="hostedUrl", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ - Link to the asset + Date the asset metadata was created """ variants: typing.Optional[typing.List[AssetVariant]] = None + alt_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="altText")] = pydantic.Field( + default=None + ) + """ + The visual description of the asset + """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/asset_folder.py b/src/webflow/types/asset_folder.py index 2406d37..b01747e 100644 --- a/src/webflow/types/asset_folder.py +++ b/src/webflow/types/asset_folder.py @@ -1,68 +1,69 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class AssetFolder(pydantic_v1.BaseModel): +class AssetFolder(UniversalBaseModel): """ Asset Folder details """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for the Asset Folder """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ User visible name for the Asset Folder """ - parent_folder: typing.Optional[str] = pydantic_v1.Field(alias="parentFolder", default=None) + parent_folder: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="parentFolder")] = ( + pydantic.Field(default=None) + ) """ Pointer to parent Asset Folder (or null if root) """ - assets: typing.Optional[typing.List[str]] = pydantic_v1.Field(default=None) + assets: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ Array of Asset instances in the folder """ - site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) """ - The unique id of the site the Asset Folder belongs to + The unique ID of the site the Asset Folder belongs to """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ Date that the Asset Folder was created on """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ Date that the Asset Folder was last updated on """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/asset_folder_list.py b/src/webflow/types/asset_folder_list.py index 0ed82b6..3badf08 100644 --- a/src/webflow/types/asset_folder_list.py +++ b/src/webflow/types/asset_folder_list.py @@ -1,42 +1,34 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .asset_folder import AssetFolder +from ..core.serialization import FieldMetadata +import pydantic from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class AssetFolderList(pydantic_v1.BaseModel): +class AssetFolderList(UniversalBaseModel): """ The Asset Folders object """ - asset_folders: typing.Optional[typing.List[AssetFolder]] = pydantic_v1.Field(alias="assetFolders", default=None) + asset_folders: typing_extensions.Annotated[ + typing.Optional[typing.List[AssetFolder]], FieldMetadata(alias="assetFolders") + ] = pydantic.Field(default=None) """ A list of Asset folders """ pagination: typing.Optional[Pagination] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/asset_upload.py b/src/webflow/types/asset_upload.py index cea12b5..fe36752 100644 --- a/src/webflow/types/asset_upload.py +++ b/src/webflow/types/asset_upload.py @@ -1,68 +1,73 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .asset_upload_upload_details import AssetUploadUploadDetails +from ..core.serialization import FieldMetadata +import pydantic +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class AssetUpload(pydantic_v1.BaseModel): - upload_details: typing.Optional[AssetUploadUploadDetails] = pydantic_v1.Field(alias="uploadDetails", default=None) +class AssetUpload(UniversalBaseModel): + upload_details: typing_extensions.Annotated[ + typing.Optional[AssetUploadUploadDetails], FieldMetadata(alias="uploadDetails") + ] = pydantic.Field(default=None) """ Metadata for uploading the asset binary """ - content_type: typing.Optional[str] = pydantic_v1.Field(alias="contentType", default=None) + content_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="contentType")] = None id: typing.Optional[str] = None - parent_folder: typing.Optional[str] = pydantic_v1.Field(alias="parentFolder", default=None) + parent_folder: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="parentFolder")] = ( + pydantic.Field(default=None) + ) """ Parent folder for the asset """ - upload_url: typing.Optional[str] = pydantic_v1.Field(alias="uploadUrl", default=None) - asset_url: typing.Optional[str] = pydantic_v1.Field(alias="assetUrl", default=None) + upload_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="uploadUrl")] = None + asset_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="assetUrl")] = pydantic.Field( + default=None + ) """ S3 link to the asset """ - hosted_url: typing.Optional[str] = pydantic_v1.Field(alias="hostedUrl", default=None) + hosted_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="hostedUrl")] = pydantic.Field( + default=None + ) """ Represents the link to the asset """ - original_file_name: typing.Optional[str] = pydantic_v1.Field(alias="originalFileName", default=None) + original_file_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="originalFileName")] = ( + pydantic.Field(default=None) + ) """ Original file name when uploaded. If not specified at time of upload, it may be extracted from the raw file name """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ Date the asset metadata was created """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ Date the asset metadata was last updated """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/asset_upload_upload_details.py b/src/webflow/types/asset_upload_upload_details.py index 40735bb..bf3e115 100644 --- a/src/webflow/types/asset_upload_upload_details.py +++ b/src/webflow/types/asset_upload_upload_details.py @@ -1,45 +1,35 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class AssetUploadUploadDetails(pydantic_v1.BaseModel): +class AssetUploadUploadDetails(UniversalBaseModel): """ Metadata for uploading the asset binary """ acl: typing.Optional[str] = None bucket: typing.Optional[str] = None - x_amz_algorithm: typing.Optional[str] = pydantic_v1.Field(alias="X-Amz-Algorithm", default=None) - x_amz_credential: typing.Optional[str] = pydantic_v1.Field(alias="X-Amz-Credential", default=None) - x_amz_date: typing.Optional[str] = pydantic_v1.Field(alias="X-Amz-Date", default=None) + x_amz_algorithm: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="X-Amz-Algorithm")] = None + x_amz_credential: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="X-Amz-Credential")] = None + x_amz_date: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="X-Amz-Date")] = None key: typing.Optional[str] = None - policy: typing.Optional[str] = pydantic_v1.Field(alias="Policy", default=None) - x_amz_signature: typing.Optional[str] = pydantic_v1.Field(alias="X-Amz-Signature", default=None) + policy: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="Policy")] = None + x_amz_signature: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="X-Amz-Signature")] = None success_action_status: typing.Optional[str] = None - content_type: typing.Optional[str] = pydantic_v1.Field(alias="content-type", default=None) - cache_control: typing.Optional[str] = pydantic_v1.Field(alias="Cache-Control", default=None) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + content_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="content-type")] = None + cache_control: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="Cache-Control")] = None - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/asset_variant.py b/src/webflow/types/asset_variant.py index ca4e205..5278667 100644 --- a/src/webflow/types/asset_variant.py +++ b/src/webflow/types/asset_variant.py @@ -1,69 +1,65 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class AssetVariant(pydantic_v1.BaseModel): - hosted_url: typing.Optional[str] = pydantic_v1.Field(alias="hostedUrl", default=None) +class AssetVariant(UniversalBaseModel): + hosted_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="hostedUrl")] = pydantic.Field( + default=None + ) """ URL of where the asset variant is hosted """ - original_file_name: typing.Optional[str] = pydantic_v1.Field(alias="originalFileName", default=None) + original_file_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="originalFileName")] = ( + pydantic.Field(default=None) + ) """ Original file name of the variant """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ Display name of the variant """ - format: typing.Optional[str] = pydantic_v1.Field(default=None) + format: typing.Optional[str] = pydantic.Field(default=None) """ format of the variant """ - width: typing.Optional[int] = pydantic_v1.Field(default=None) + width: typing.Optional[int] = pydantic.Field(default=None) """ Width in pixels """ - height: typing.Optional[int] = pydantic_v1.Field(default=None) + height: typing.Optional[int] = pydantic.Field(default=None) """ Height in pixels """ - quality: typing.Optional[int] = pydantic_v1.Field(default=None) + quality: typing.Optional[int] = pydantic.Field(default=None) """ Value between 0 and 100 representing the image quality """ - error: typing.Optional[str] = pydantic_v1.Field(default=None) + error: typing.Optional[str] = pydantic.Field(default=None) """ Any associated validation errors """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/assets.py b/src/webflow/types/assets.py index 1d4dbfc..380b0de 100644 --- a/src/webflow/types/assets.py +++ b/src/webflow/types/assets.py @@ -1,34 +1,24 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .asset import Asset +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class Assets(pydantic_v1.BaseModel): +class Assets(UniversalBaseModel): """ A list of assets """ assets: typing.Optional[typing.List[Asset]] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/authorization.py b/src/webflow/types/authorization.py index ecb2ed7..7668ace 100644 --- a/src/webflow/types/authorization.py +++ b/src/webflow/types/authorization.py @@ -1,36 +1,26 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -from .application import Application from .authorization_authorization import AuthorizationAuthorization +import pydantic +from .application import Application +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Authorization(pydantic_v1.BaseModel): - authorization: typing.Optional[AuthorizationAuthorization] = pydantic_v1.Field(default=None) +class Authorization(UniversalBaseModel): + authorization: typing.Optional[AuthorizationAuthorization] = pydantic.Field(default=None) """ The Authorization object """ application: typing.Optional[Application] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/authorization_authorization.py b/src/webflow/types/authorization_authorization.py index 9410526..b732aac 100644 --- a/src/webflow/types/authorization_authorization.py +++ b/src/webflow/types/authorization_authorization.py @@ -1,68 +1,67 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions +import datetime as dt +from ..core.serialization import FieldMetadata from .authorization_authorization_authorized_to import AuthorizationAuthorizationAuthorizedTo +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class AuthorizationAuthorization(pydantic_v1.BaseModel): +class AuthorizationAuthorization(UniversalBaseModel): """ The Authorization object """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: typing.Optional[str] = pydantic.Field(default=None) """ - The unique id of the Authorization instance + The unique ID of the Authorization instance """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ The date the Authorization was created """ - last_used: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUsed", default=None) + last_used: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUsed")] = ( + pydantic.Field(default=None) + ) """ The date the Authorization was last used """ - grant_type: typing.Optional[str] = pydantic_v1.Field(alias="grantType", default=None) + grant_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="grantType")] = pydantic.Field( + default=None + ) """ The grant type of the Authorization """ - rate_limit: typing.Optional[int] = pydantic_v1.Field(alias="rateLimit", default=None) + rate_limit: typing_extensions.Annotated[typing.Optional[int], FieldMetadata(alias="rateLimit")] = pydantic.Field( + default=None + ) """ The default rate limit for the Authorization (requests/min) """ - scope: typing.Optional[str] = pydantic_v1.Field(default=None) + scope: typing.Optional[str] = pydantic.Field(default=None) """ Comma separted list of OAuth scopes corresponding to the Authorization """ - authorized_to: typing.Optional[AuthorizationAuthorizationAuthorizedTo] = pydantic_v1.Field( - alias="authorizedTo", default=None - ) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + authorized_to: typing_extensions.Annotated[ + typing.Optional[AuthorizationAuthorizationAuthorizedTo], FieldMetadata(alias="authorizedTo") + ] = None - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/authorization_authorization_authorized_to.py b/src/webflow/types/authorization_authorization_authorized_to.py index cb59ffc..c4316ab 100644 --- a/src/webflow/types/authorization_authorization_authorized_to.py +++ b/src/webflow/types/authorization_authorization_authorized_to.py @@ -1,44 +1,40 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class AuthorizationAuthorizationAuthorizedTo(pydantic_v1.BaseModel): - site_ids: typing.Optional[typing.List[typing.Any]] = pydantic_v1.Field(alias="siteIds", default=None) +class AuthorizationAuthorizationAuthorizedTo(UniversalBaseModel): + site_ids: typing_extensions.Annotated[ + typing.Optional[typing.List[typing.Optional[typing.Any]]], FieldMetadata(alias="siteIds") + ] = pydantic.Field(default=None) """ Array of Sites this app is authorized to """ - workspace_ids: typing.Optional[typing.List[typing.Any]] = pydantic_v1.Field(alias="workspaceIds", default=None) + workspace_ids: typing_extensions.Annotated[ + typing.Optional[typing.List[typing.Optional[typing.Any]]], FieldMetadata(alias="workspaceIds") + ] = pydantic.Field(default=None) """ Array of Workspaces this app is authorized to """ - user_ids: typing.Optional[typing.List[typing.Any]] = pydantic_v1.Field(alias="userIds", default=None) + user_ids: typing_extensions.Annotated[ + typing.Optional[typing.List[typing.Optional[typing.Any]]], FieldMetadata(alias="userIds") + ] = pydantic.Field(default=None) """ Array of Users this app is authorized to """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/authorized_user.py b/src/webflow/types/authorized_user.py index 80c4931..d91c8c6 100644 --- a/src/webflow/types/authorized_user.py +++ b/src/webflow/types/authorized_user.py @@ -1,49 +1,43 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class AuthorizedUser(pydantic_v1.BaseModel): - id: typing.Optional[str] = pydantic_v1.Field(default=None) +class AuthorizedUser(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) """ - The unique id of the user + The unique ID of the user """ - email: typing.Optional[str] = pydantic_v1.Field(default=None) + email: typing.Optional[str] = pydantic.Field(default=None) """ The user's email address """ - first_name: typing.Optional[str] = pydantic_v1.Field(alias="firstName", default=None) + first_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="firstName")] = pydantic.Field( + default=None + ) """ The user's first name """ - last_name: typing.Optional[str] = pydantic_v1.Field(alias="lastName", default=None) + last_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastName")] = pydantic.Field( + default=None + ) """ The user's last name """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/bad_request_error_body.py b/src/webflow/types/bad_request_error_body.py index 6403cc4..5c1277c 100644 --- a/src/webflow/types/bad_request_error_body.py +++ b/src/webflow/types/bad_request_error_body.py @@ -1,7 +1,6 @@ # This file was auto-generated by Fern from our API Definition. import typing - from .invalid_domain import InvalidDomain from .no_domains import NoDomains diff --git a/src/webflow/types/bulk_collection_item.py b/src/webflow/types/bulk_collection_item.py new file mode 100644 index 0000000..4d17d13 --- /dev/null +++ b/src/webflow/types/bulk_collection_item.py @@ -0,0 +1,75 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +from .bulk_collection_item_field_data import BulkCollectionItemFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class BulkCollectionItem(UniversalBaseModel): + """ + The fields that define the schema for a given Item are based on the Collection that Item belongs to. Beyond the user defined fields, there are a handful of additional fields that are automatically created for all items + """ + + id: str = pydantic.Field() + """ + Unique identifier for the Item + """ + + cms_locale_ids: typing_extensions.Annotated[ + typing.Optional[typing.List[str]], FieldMetadata(alias="cmsLocaleIds") + ] = pydantic.Field(default=None) + """ + Array of identifiers for the locales where the item will be created + """ + + last_published: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastPublished")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last published + """ + + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last updated + """ + + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) + """ + The date the item was created + """ + + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( + default=None + ) + """ + Boolean determining if the Item is set to archived + """ + + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( + default=None + ) + """ + Boolean determining if the Item is set to draft + """ + + field_data: typing_extensions.Annotated[ + typing.Optional[BulkCollectionItemFieldData], FieldMetadata(alias="fieldData") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/bulk_collection_item_field_data.py b/src/webflow/types/bulk_collection_item_field_data.py new file mode 100644 index 0000000..9b977a3 --- /dev/null +++ b/src/webflow/types/bulk_collection_item_field_data.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class BulkCollectionItemFieldData(UniversalBaseModel): + name: typing.Optional[str] = pydantic.Field(default=None) + """ + Name of the Item + """ + + slug: typing.Optional[str] = pydantic.Field(default=None) + """ + URL structure of the Item in your site. Note: Updates to an item slug will break all links referencing the old slug. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection.py b/src/webflow/types/collection.py index 4be489d..81e0f90 100644 --- a/src/webflow/types/collection.py +++ b/src/webflow/types/collection.py @@ -1,69 +1,68 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from ..core.serialization import FieldMetadata +import datetime as dt from .field import Field +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Collection(pydantic_v1.BaseModel): +class Collection(UniversalBaseModel): """ A collection object """ - id: str = pydantic_v1.Field() + id: str = pydantic.Field() """ Unique identifier for a Collection """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ Name given to the Collection """ - singular_name: typing.Optional[str] = pydantic_v1.Field(alias="singularName", default=None) + singular_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="singularName")] = ( + pydantic.Field(default=None) + ) """ The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”) """ - slug: typing.Optional[str] = pydantic_v1.Field(default=None) + slug: typing.Optional[str] = pydantic.Field(default=None) """ Slug of Collection in Site URL structure """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ The date the collection was created """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ The date the collection was last updated """ - fields: typing.List[Field] = pydantic_v1.Field() + fields: typing.List[Field] = pydantic.Field() """ The list of fields in the Collection """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item.py b/src/webflow/types/collection_item.py index d7e2e1d..6551900 100644 --- a/src/webflow/types/collection_item.py +++ b/src/webflow/types/collection_item.py @@ -1,71 +1,77 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata from .collection_item_field_data import CollectionItemFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class CollectionItem(pydantic_v1.BaseModel): +class CollectionItem(UniversalBaseModel): """ - The fields that define the schema for a given Item are based on the Collection that Item belongs to. Beyond the user defined fields, there are a handful of additional fields that are automatically created for all items + A Collection Item represents a single entry in your collection. Each item includes: + + - **System metadata** - Automatically managed fields like IDs and timestamp
+ - **Status flags** - Controls for managing content state: `isDraft`, `isArchived `
+ - **Content fields** - Stored in `fieldData`. Each item needs a `name` and `slug`, and may include additional fields matching your collection's schema definition. """ - id: str = pydantic_v1.Field() + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for the Item """ - cms_locale_id: typing.Optional[str] = pydantic_v1.Field(alias="cmsLocaleId", default=None) + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) """ Identifier for the locale of the CMS item """ - last_published: typing.Optional[str] = pydantic_v1.Field(alias="lastPublished", default=None) + last_published: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastPublished")] = ( + pydantic.Field(default=None) + ) """ The date the item was last published """ - last_updated: typing.Optional[str] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ The date the item was last updated """ - created_on: typing.Optional[str] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) """ The date the item was created """ - is_archived: typing.Optional[bool] = pydantic_v1.Field(alias="isArchived", default=None) + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( + default=None + ) """ Boolean determining if the Item is set to archived """ - is_draft: typing.Optional[bool] = pydantic_v1.Field(alias="isDraft", default=None) + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( + default=None + ) """ Boolean determining if the Item is set to draft """ - field_data: typing.Optional[CollectionItemFieldData] = pydantic_v1.Field(alias="fieldData", default=None) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + field_data: typing_extensions.Annotated[CollectionItemFieldData, FieldMetadata(alias="fieldData")] - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_field_data.py b/src/webflow/types/collection_item_field_data.py index 19b8588..651dbe8 100644 --- a/src/webflow/types/collection_item_field_data.py +++ b/src/webflow/types/collection_item_field_data.py @@ -1,37 +1,27 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class CollectionItemFieldData(pydantic_v1.BaseModel): - name: typing.Optional[str] = pydantic_v1.Field(default=None) +class CollectionItemFieldData(UniversalBaseModel): + name: str = pydantic.Field() """ Name of the Item """ - slug: typing.Optional[str] = pydantic_v1.Field(default=None) + slug: str = pydantic.Field() """ URL structure of the Item in your site. Note: Updates to an item slug will break all links referencing the old slug. """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_list.py b/src/webflow/types/collection_item_list.py index 2414299..a1ff6d9 100644 --- a/src/webflow/types/collection_item_list.py +++ b/src/webflow/types/collection_item_list.py @@ -1,40 +1,30 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .collection_item import CollectionItem +import pydantic from .collection_item_list_pagination import CollectionItemListPagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class CollectionItemList(pydantic_v1.BaseModel): +class CollectionItemList(UniversalBaseModel): """ Results from collection items list """ - items: typing.Optional[typing.List[CollectionItem]] = pydantic_v1.Field(default=None) + items: typing.Optional[typing.List[CollectionItem]] = pydantic.Field(default=None) """ List of Items within the collection """ pagination: typing.Optional[CollectionItemListPagination] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_list_no_pagination.py b/src/webflow/types/collection_item_list_no_pagination.py new file mode 100644 index 0000000..2b3f556 --- /dev/null +++ b/src/webflow/types/collection_item_list_no_pagination.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .collection_item import CollectionItem +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemListNoPagination(UniversalBaseModel): + """ + Results from collection items list + """ + + items: typing.Optional[typing.List[CollectionItem]] = pydantic.Field(default=None) + """ + List of Items within the collection + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_list_pagination.py b/src/webflow/types/collection_item_list_pagination.py index 3a7380b..394953b 100644 --- a/src/webflow/types/collection_item_list_pagination.py +++ b/src/webflow/types/collection_item_list_pagination.py @@ -1,42 +1,32 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class CollectionItemListPagination(pydantic_v1.BaseModel): - limit: typing.Optional[float] = pydantic_v1.Field(default=None) +class CollectionItemListPagination(UniversalBaseModel): + limit: typing.Optional[float] = pydantic.Field(default=None) """ The limit specified in the request """ - offset: typing.Optional[float] = pydantic_v1.Field(default=None) + offset: typing.Optional[float] = pydantic.Field(default=None) """ The offset specified for pagination """ - total: typing.Optional[float] = pydantic_v1.Field(default=None) + total: typing.Optional[float] = pydantic.Field(default=None) """ Total number of items in the collection """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_patch_single.py b/src/webflow/types/collection_item_patch_single.py new file mode 100644 index 0000000..17266b0 --- /dev/null +++ b/src/webflow/types/collection_item_patch_single.py @@ -0,0 +1,75 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemPatchSingle(UniversalBaseModel): + """ + The fields that define the schema for a given Item are based on the Collection that Item belongs to. Beyond the user defined fields, there are a handful of additional fields that are automatically created for all items + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for the Item + """ + + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) + """ + Identifier for the locale of the CMS item + """ + + last_published: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastPublished")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last published + """ + + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last updated + """ + + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) + """ + The date the item was created + """ + + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( + default=None + ) + """ + Boolean determining if the Item is set to archived + """ + + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( + default=None + ) + """ + Boolean determining if the Item is set to draft + """ + + field_data: typing_extensions.Annotated[ + typing.Optional[CollectionItemPatchSingleFieldData], FieldMetadata(alias="fieldData") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_patch_single_field_data.py b/src/webflow/types/collection_item_patch_single_field_data.py new file mode 100644 index 0000000..2d5d5f8 --- /dev/null +++ b/src/webflow/types/collection_item_patch_single_field_data.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemPatchSingleFieldData(UniversalBaseModel): + name: typing.Optional[str] = pydantic.Field(default=None) + """ + Name of the Item + """ + + slug: typing.Optional[str] = pydantic.Field(default=None) + """ + URL structure of the Item in your site. Note: Updates to an item slug will break all links referencing the old slug. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_post_single.py b/src/webflow/types/collection_item_post_single.py new file mode 100644 index 0000000..3a9bafa --- /dev/null +++ b/src/webflow/types/collection_item_post_single.py @@ -0,0 +1,77 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .collection_item_post_single_field_data import CollectionItemPostSingleFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemPostSingle(UniversalBaseModel): + """ + A Collection Item represents a single entry in your collection. Each item includes: + + - **System metadata** - Automatically managed fields like IDs and timestamp
+ - **Status flags** - Controls for managing content state: `isDraft`, `isArchived `
+ - **Content fields** - Stored in `fieldData`. Each item needs a `name` and `slug`, and may include additional fields matching your collection's schema definition. + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for the Item + """ + + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) + """ + Identifier for the locale of the CMS item + """ + + last_published: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastPublished")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last published + """ + + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last updated + """ + + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) + """ + The date the item was created + """ + + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( + default=None + ) + """ + Boolean determining if the Item is in an archived state. + """ + + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( + default=None + ) + """ + Boolean determining if the Item is in a draft state. + """ + + field_data: typing_extensions.Annotated[CollectionItemPostSingleFieldData, FieldMetadata(alias="fieldData")] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_post_single_field_data.py b/src/webflow/types/collection_item_post_single_field_data.py new file mode 100644 index 0000000..ae86f3b --- /dev/null +++ b/src/webflow/types/collection_item_post_single_field_data.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CollectionItemPostSingleFieldData(UniversalBaseModel): + name: str = pydantic.Field() + """ + Name of the Item + """ + + slug: str = pydantic.Field() + """ + URL structure of the Item in your site. Note: Updates to an item slug will break all links referencing the old slug. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_with_id_input.py b/src/webflow/types/collection_item_with_id_input.py new file mode 100644 index 0000000..df3cd7e --- /dev/null +++ b/src/webflow/types/collection_item_with_id_input.py @@ -0,0 +1,75 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +from .collection_item_with_id_input_field_data import CollectionItemWithIdInputFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemWithIdInput(UniversalBaseModel): + """ + The fields that define the schema for a given Item are based on the Collection that Item belongs to. Beyond the user defined fields, there are a handful of additional fields that are automatically created for all items + """ + + id: str = pydantic.Field() + """ + Unique identifier for the Item + """ + + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) + """ + Identifier for the locale of the CMS item + """ + + last_published: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastPublished")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last published + """ + + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last updated + """ + + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) + """ + The date the item was created + """ + + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( + default=None + ) + """ + Boolean determining if the Item is set to archived + """ + + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( + default=None + ) + """ + Boolean determining if the Item is set to draft + """ + + field_data: typing_extensions.Annotated[ + typing.Optional[CollectionItemWithIdInputFieldData], FieldMetadata(alias="fieldData") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_with_id_input_field_data.py b/src/webflow/types/collection_item_with_id_input_field_data.py new file mode 100644 index 0000000..3109eb2 --- /dev/null +++ b/src/webflow/types/collection_item_with_id_input_field_data.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemWithIdInputFieldData(UniversalBaseModel): + name: typing.Optional[str] = pydantic.Field(default=None) + """ + Name of the Item + """ + + slug: typing.Optional[str] = pydantic.Field(default=None) + """ + URL structure of the Item in your site. Note: Updates to an item slug will break all links referencing the old slug. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_list.py b/src/webflow/types/collection_list.py index 4e5a51c..a1ac376 100644 --- a/src/webflow/types/collection_list.py +++ b/src/webflow/types/collection_list.py @@ -1,33 +1,23 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .collection_list_array_item import CollectionListArrayItem +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class CollectionList(pydantic_v1.BaseModel): - collections: typing.Optional[typing.List[CollectionListArrayItem]] = pydantic_v1.Field(default=None) +class CollectionList(UniversalBaseModel): + collections: typing.Optional[typing.List[CollectionListArrayItem]] = pydantic.Field(default=None) """ An array of Collections """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_list_array_item.py b/src/webflow/types/collection_list_array_item.py index 734f947..77e518a 100644 --- a/src/webflow/types/collection_list_array_item.py +++ b/src/webflow/types/collection_list_array_item.py @@ -1,63 +1,62 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from ..core.serialization import FieldMetadata +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class CollectionListArrayItem(pydantic_v1.BaseModel): +class CollectionListArrayItem(UniversalBaseModel): """ A collection object """ - id: str = pydantic_v1.Field() + id: str = pydantic.Field() """ Unique identifier for a Collection """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ Name given to the Collection """ - singular_name: typing.Optional[str] = pydantic_v1.Field(alias="singularName", default=None) + singular_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="singularName")] = ( + pydantic.Field(default=None) + ) """ The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”) """ - slug: typing.Optional[str] = pydantic_v1.Field(default=None) + slug: typing.Optional[str] = pydantic.Field(default=None) """ Slug of Collection in Site URL structure """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ The date the collection was created """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ The date the collection was last updated """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/component.py b/src/webflow/types/component.py new file mode 100644 index 0000000..ae6fea2 --- /dev/null +++ b/src/webflow/types/component.py @@ -0,0 +1,46 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Component(UniversalBaseModel): + """ + The Component object + """ + + id: str = pydantic.Field() + """ + Unique identifier for the Component + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + Component Name + """ + + group: typing.Optional[str] = pydantic.Field(default=None) + """ + The group that the component belongs to + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + Component Description + """ + + readonly: typing.Optional[bool] = pydantic.Field(default=None) + """ + Indicates whether the component is read-only. Components that cannot be updated within this Site are set to readonly. Workspace Libraries are a good example. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/component_dom.py b/src/webflow/types/component_dom.py new file mode 100644 index 0000000..3f76c81 --- /dev/null +++ b/src/webflow/types/component_dom.py @@ -0,0 +1,35 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .node import Node +from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ComponentDom(UniversalBaseModel): + """ + The Component DOM schema represents the content structure of a component. Similar to Page DOM, it captures various content nodes and their associated attributes, but specifically for a component's structure. Each node has a unique identifier and can contain text, images, or nested component instances. + """ + + component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = ( + pydantic.Field(default=None) + ) + """ + Component ID + """ + + nodes: typing.Optional[typing.List[Node]] = None + pagination: typing.Optional[Pagination] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/component_instance_node_property_overrides_write.py b/src/webflow/types/component_instance_node_property_overrides_write.py new file mode 100644 index 0000000..6c7d69c --- /dev/null +++ b/src/webflow/types/component_instance_node_property_overrides_write.py @@ -0,0 +1,39 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +import typing +from .component_instance_node_property_overrides_write_property_overrides_item import ( + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, +) +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ComponentInstanceNodePropertyOverridesWrite(UniversalBaseModel): + """ + Update text property overrides of a component instance + """ + + node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() + """ + Node UUID + """ + + property_overrides: typing_extensions.Annotated[ + typing.List[ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem], + FieldMetadata(alias="propertyOverrides"), + ] = pydantic.Field() + """ + A list of component instance properties to override within the specified secondary locale. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/component_instance_node_property_overrides_write_property_overrides_item.py b/src/webflow/types/component_instance_node_property_overrides_write_property_overrides_item.py new file mode 100644 index 0000000..313b0d6 --- /dev/null +++ b/src/webflow/types/component_instance_node_property_overrides_write_property_overrides_item.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem(UniversalBaseModel): + property_id: typing_extensions.Annotated[str, FieldMetadata(alias="propertyId")] = pydantic.Field() + """ + The ID of the property. + """ + + text: str = pydantic.Field() + """ + The new string or HTML value used to override the component instance property value. + The provided value must be compatible with the type of the component instance property. + For example, attempting to override a single-line plain-text property with a multi-line + value will result in an error. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/component_list.py b/src/webflow/types/component_list.py new file mode 100644 index 0000000..cd16188 --- /dev/null +++ b/src/webflow/types/component_list.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .component import Component +from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ComponentList(UniversalBaseModel): + """ + List of Components on a site. + """ + + components: typing.Optional[typing.List[Component]] = None + pagination: typing.Optional[Pagination] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/component_node.py b/src/webflow/types/component_node.py new file mode 100644 index 0000000..fa5f69d --- /dev/null +++ b/src/webflow/types/component_node.py @@ -0,0 +1,43 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .component_property import ComponentProperty +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ComponentNode(UniversalBaseModel): + """ + Represents a component instance within the DOM. It contains details about the component instance, such as its type and properties. + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Node UUID + """ + + component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = ( + pydantic.Field(default=None) + ) + """ + Component ID + """ + + property_overrides: typing_extensions.Annotated[ + typing.Optional[typing.List[ComponentProperty]], FieldMetadata(alias="propertyOverrides") + ] = pydantic.Field(default=None) + """ + List of component properties with overrides for a component instance. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/component_properties.py b/src/webflow/types/component_properties.py new file mode 100644 index 0000000..f37e71b --- /dev/null +++ b/src/webflow/types/component_properties.py @@ -0,0 +1,35 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .component_property import ComponentProperty +from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ComponentProperties(UniversalBaseModel): + """ + The Component Properties schema represents a list of properties that store text content. Each property has a unique identifier and can be of different types like plain text or rich text. The schema also provides pagination details for scenarios where there more properties than the limit. + """ + + component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = ( + pydantic.Field(default=None) + ) + """ + Component ID + """ + + properties: typing.Optional[typing.List[ComponentProperty]] = None + pagination: typing.Optional[Pagination] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/component_property.py b/src/webflow/types/component_property.py new file mode 100644 index 0000000..7f09d8e --- /dev/null +++ b/src/webflow/types/component_property.py @@ -0,0 +1,47 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .component_property_type import ComponentPropertyType +from .text import Text +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ComponentProperty(UniversalBaseModel): + """ + Represents a property of a component instance in the DOM. A property contains a list of both the raw text and the HTML representation, allowing for flexibility in rendering and processing. Additional attributes can be associated with the text for styling or other purposes. + """ + + property_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="propertyId")] = pydantic.Field( + default=None + ) + """ + The ID of the property. + """ + + type: typing.Optional[ComponentPropertyType] = pydantic.Field(default=None) + """ + The type of the property. + """ + + label: typing.Optional[str] = pydantic.Field(default=None) + """ + The label of the property in the UI. + """ + + text: typing.Optional[Text] = pydantic.Field(default=None) + """ + Represents text content within the DOM. It contains both the raw text and its HTML representation. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/component_property_type.py b/src/webflow/types/component_property_type.py new file mode 100644 index 0000000..117b2fe --- /dev/null +++ b/src/webflow/types/component_property_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ComponentPropertyType = typing.Union[typing.Literal["Plain Text", "Rich Text", "Alt Text"], typing.Any] diff --git a/src/webflow/types/conflict_error_body.py b/src/webflow/types/conflict_error_body.py index 7f34146..2ec15f8 100644 --- a/src/webflow/types/conflict_error_body.py +++ b/src/webflow/types/conflict_error_body.py @@ -1,7 +1,6 @@ # This file was auto-generated by Fern from our API Definition. import typing - from .duplicate_user_email import DuplicateUserEmail from .user_limit_reached import UserLimitReached diff --git a/src/webflow/types/custom_code_block.py b/src/webflow/types/custom_code_block.py index 4252be7..f52e4b8 100644 --- a/src/webflow/types/custom_code_block.py +++ b/src/webflow/types/custom_code_block.py @@ -1,61 +1,60 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from ..core.serialization import FieldMetadata +import pydantic from .custom_code_block_type import CustomCodeBlockType from .scripts import Scripts +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class CustomCodeBlock(pydantic_v1.BaseModel): +class CustomCodeBlock(UniversalBaseModel): """ A specific instance of Custom Code applied to a Site or Page """ - site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) """ - The Site id where the custom code was applied + The Site ID where the custom code was applied """ - page_id: typing.Optional[str] = pydantic_v1.Field(alias="pageId", default=None) + page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = pydantic.Field( + default=None + ) """ - The Page id (if applied at Page-level) + The Page ID (if applied at Page-level) """ - type: typing.Optional[CustomCodeBlockType] = pydantic_v1.Field(default=None) + type: typing.Optional[CustomCodeBlockType] = pydantic.Field(default=None) """ Whether the Custom Code script is applied at the Site-level or Page-level """ scripts: typing.Optional[Scripts] = None - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ The date the Block was created """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ The date the Block was most recently updated """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/custom_code_block_type.py b/src/webflow/types/custom_code_block_type.py index 2d1673d..4b8cf2e 100644 --- a/src/webflow/types/custom_code_block_type.py +++ b/src/webflow/types/custom_code_block_type.py @@ -1,21 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class CustomCodeBlockType(str, enum.Enum): - """ - Whether the Custom Code script is applied at the Site-level or Page-level - """ - - PAGE = "page" - SITE = "site" - - def visit(self, page: typing.Callable[[], T_Result], site: typing.Callable[[], T_Result]) -> T_Result: - if self is CustomCodeBlockType.PAGE: - return page() - if self is CustomCodeBlockType.SITE: - return site() +CustomCodeBlockType = typing.Union[typing.Literal["page", "site"], typing.Any] diff --git a/src/webflow/types/custom_code_hosted_response.py b/src/webflow/types/custom_code_hosted_response.py index 61011c3..9bc97cf 100644 --- a/src/webflow/types/custom_code_hosted_response.py +++ b/src/webflow/types/custom_code_hosted_response.py @@ -1,73 +1,75 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class CustomCodeHostedResponse(pydantic_v1.BaseModel): +class CustomCodeHostedResponse(UniversalBaseModel): """ Registered custom code for application """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: typing.Optional[str] = pydantic.Field(default=None) """ Human readable id, derived from the user-specified display name """ - can_copy: typing.Optional[bool] = pydantic_v1.Field(alias="canCopy", default=None) + can_copy: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="canCopy")] = pydantic.Field( + default=None + ) """ Define whether the script can be copied on site duplication and transfer """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ User-facing name for the script. Must be between 1 and 50 alphanumeric characters """ - hosted_location: typing.Optional[str] = pydantic_v1.Field(alias="hostedLocation", default=None) + hosted_location: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="hostedLocation")] = ( + pydantic.Field(default=None) + ) """ URI for an externally hosted script location """ - integrity_hash: typing.Optional[str] = pydantic_v1.Field(alias="integrityHash", default=None) + integrity_hash: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="integrityHash")] = ( + pydantic.Field(default=None) + ) """ Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) """ - created_on: typing.Optional[str] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) """ Timestamp when the script version was created """ - last_updated: typing.Optional[str] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ Timestamp when the script version was last updated """ - version: typing.Optional[str] = pydantic_v1.Field(default=None) + version: typing.Optional[str] = pydantic.Field(default=None) """ A Semantic Version (SemVer) string, denoting the version of the script """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/custom_code_inline_response.py b/src/webflow/types/custom_code_inline_response.py index a0301c1..7934ec5 100644 --- a/src/webflow/types/custom_code_inline_response.py +++ b/src/webflow/types/custom_code_inline_response.py @@ -1,73 +1,75 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class CustomCodeInlineResponse(pydantic_v1.BaseModel): +class CustomCodeInlineResponse(UniversalBaseModel): """ Registered custom code for application """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: typing.Optional[str] = pydantic.Field(default=None) """ Human readable id, derived from the user-specified display name """ - can_copy: typing.Optional[bool] = pydantic_v1.Field(alias="canCopy", default=None) + can_copy: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="canCopy")] = pydantic.Field( + default=None + ) """ Define whether the script can be copied on site duplication and transfer """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ User-facing name for the script. Must be between 1 and 50 alphanumeric characters """ - hosted_location: typing.Optional[str] = pydantic_v1.Field(alias="hostedLocation", default=None) + hosted_location: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="hostedLocation")] = ( + pydantic.Field(default=None) + ) """ URI for an externally hosted script location """ - integrity_hash: typing.Optional[str] = pydantic_v1.Field(alias="integrityHash", default=None) + integrity_hash: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="integrityHash")] = ( + pydantic.Field(default=None) + ) """ Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) """ - created_on: typing.Optional[str] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) """ Timestamp when the script version was created """ - last_updated: typing.Optional[str] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ Timestamp when the script version was last updated """ - version: typing.Optional[str] = pydantic_v1.Field(default=None) + version: typing.Optional[str] = pydantic.Field(default=None) """ A Semantic Version (SemVer) string, denoting the version of the script """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/dom.py b/src/webflow/types/dom.py index d922f40..ce15a6a 100644 --- a/src/webflow/types/dom.py +++ b/src/webflow/types/dom.py @@ -1,20 +1,23 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from ..core.serialization import FieldMetadata +import pydantic from .node import Node from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Dom(pydantic_v1.BaseModel): +class Dom(UniversalBaseModel): """ - The DOM (Document Object Model) schema represents the content structure of a web page. It captures various content nodes, such as text and images, along with their associated attributes. Each node has a unique identifier and can be of different types like text or image. The schema also provides pagination details for scenarios where the content nodes are too many to be fetched in a single request. + The DOM (Document Object Model) schema represents the content structure of a web page or component. It captures various content nodes along with their associated attributes. Each node has a unique identifier and can be of different types like text, image or component-instance. The schema also provides pagination details for scenarios where the content nodes are too many to be fetched in a single request. """ - page_id: typing.Optional[str] = pydantic_v1.Field(alias="pageId", default=None) + page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = pydantic.Field( + default=None + ) """ Page ID """ @@ -22,22 +25,11 @@ class Dom(pydantic_v1.BaseModel): nodes: typing.Optional[typing.List[Node]] = None pagination: typing.Optional[Pagination] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/domain.py b/src/webflow/types/domain.py index fdd9a92..e678d1d 100644 --- a/src/webflow/types/domain.py +++ b/src/webflow/types/domain.py @@ -1,37 +1,37 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import typing_extensions +import datetime as dt +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Domain(pydantic_v1.BaseModel): - id: str = pydantic_v1.Field() +class Domain(UniversalBaseModel): + id: str = pydantic.Field() """ Unique identifier for the Domain """ - url: typing.Optional[str] = pydantic_v1.Field(default=None) + url: typing.Optional[str] = pydantic.Field(default=None) """ The registered Domain name """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + pydantic.Field(default=None) + ) + """ + The date the custom domain was last published to + """ - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/domains.py b/src/webflow/types/domains.py index dcfd0ef..c34d85b 100644 --- a/src/webflow/types/domains.py +++ b/src/webflow/types/domains.py @@ -1,32 +1,24 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .domain import Domain +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class Domains(pydantic_v1.BaseModel): - custom_domains: typing.Optional[typing.List[Domain]] = pydantic_v1.Field(alias="customDomains", default=None) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} +class Domains(UniversalBaseModel): + custom_domains: typing_extensions.Annotated[ + typing.Optional[typing.List[Domain]], FieldMetadata(alias="customDomains") + ] = None - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/duplicate_user_email.py b/src/webflow/types/duplicate_user_email.py index 31cf125..4a44039 100644 --- a/src/webflow/types/duplicate_user_email.py +++ b/src/webflow/types/duplicate_user_email.py @@ -1,5 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .error import Error +import typing -DuplicateUserEmail = Error +DuplicateUserEmail = typing.Optional[typing.Any] diff --git a/src/webflow/types/ecommerce_settings.py b/src/webflow/types/ecommerce_settings.py index 6f58259..d719e64 100644 --- a/src/webflow/types/ecommerce_settings.py +++ b/src/webflow/types/ecommerce_settings.py @@ -1,48 +1,45 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from ..core.serialization import FieldMetadata +import pydantic +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class EcommerceSettings(pydantic_v1.BaseModel): +class EcommerceSettings(UniversalBaseModel): """ Ecommerce settings for a Webflow Site """ - site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) """ The identifier of the Site """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ Date that the Site was created on """ - default_currency: typing.Optional[str] = pydantic_v1.Field(alias="defaultCurrency", default=None) + default_currency: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="defaultCurrency")] = ( + pydantic.Field(default=None) + ) """ The three-letter ISO currency code for the Site """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/error.py b/src/webflow/types/error.py index ead5b4d..0fef21c 100644 --- a/src/webflow/types/error.py +++ b/src/webflow/types/error.py @@ -1,50 +1,42 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +from .error_code import ErrorCode +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -from .error_details_item import ErrorDetailsItem - -class Error(pydantic_v1.BaseModel): - code: typing.Optional[str] = pydantic_v1.Field(default=None) +class Error(UniversalBaseModel): + code: typing.Optional[ErrorCode] = pydantic.Field(default=None) """ Error code """ - message: typing.Optional[str] = pydantic_v1.Field(default=None) + message: typing.Optional[str] = pydantic.Field(default=None) """ Error message """ - external_reference: typing.Optional[str] = pydantic_v1.Field(alias="externalReference", default=None) + external_reference: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="externalReference")] = ( + pydantic.Field(default=None) + ) """ Link to more information """ - details: typing.Optional[typing.List[ErrorDetailsItem]] = pydantic_v1.Field(default=None) + details: typing.Optional[typing.List[typing.Optional[typing.Any]]] = pydantic.Field(default=None) """ Array of errors """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/error_code.py b/src/webflow/types/error_code.py new file mode 100644 index 0000000..f9149eb --- /dev/null +++ b/src/webflow/types/error_code.py @@ -0,0 +1,38 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ErrorCode = typing.Union[ + typing.Literal[ + "bad_request", + "collection_not_found", + "conflict", + "duplicate_collection", + "duplicate_user_email", + "ecommerce_not_enabled", + "forbidden", + "forms_require_republish", + "incompatible_webhook_filter", + "internal_error", + "invalid_auth_version", + "invalid_credentials", + "invalid_domain", + "invalid_user_email", + "item_not_found", + "missing_scopes", + "no_domains", + "not_authorized", + "not_enterprise_plan_site", + "not_enterprise_plan_workspace", + "order_not_found", + "resource_not_found", + "too_many_requests", + "unsupported_version", + "unsupported_webhook_trigger_type", + "user_limit_reached", + "user_not_found", + "users_not_enabled", + "validation_error", + ], + typing.Any, +] diff --git a/src/webflow/types/field.py b/src/webflow/types/field.py index d5823cd..40233a9 100644 --- a/src/webflow/types/field.py +++ b/src/webflow/types/field.py @@ -1,69 +1,63 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .field_type import FieldType +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Field(pydantic_v1.BaseModel): +class Field(UniversalBaseModel): """ The details of a field in a collection """ - id: str = pydantic_v1.Field() + id: str = pydantic.Field() """ Unique identifier for a Field """ - is_required: bool = pydantic_v1.Field(alias="isRequired") + is_required: typing_extensions.Annotated[bool, FieldMetadata(alias="isRequired")] = pydantic.Field() """ define whether a field is required in a collection """ - is_editable: typing.Optional[bool] = pydantic_v1.Field(alias="isEditable", default=None) + is_editable: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEditable")] = pydantic.Field( + default=None + ) """ Define whether the field is editable """ - type: FieldType = pydantic_v1.Field() + type: FieldType = pydantic.Field() """ Choose these appropriate field type for your collection data """ - slug: typing.Optional[str] = pydantic_v1.Field(default=None) + slug: typing.Optional[str] = pydantic.Field(default=None) """ Slug of Field in Site URL structure. Slugs should be all lowercase with no spaces. Any spaces will be converted to "-." """ - display_name: str = pydantic_v1.Field(alias="displayName") + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() """ The name of a field """ - help_text: typing.Optional[str] = pydantic_v1.Field(alias="helpText", default=None) + help_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="helpText")] = pydantic.Field( + default=None + ) """ Additional text to help anyone filling out this field """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/field_type.py b/src/webflow/types/field_type.py index 2b60793..6318a3d 100644 --- a/src/webflow/types/field_type.py +++ b/src/webflow/types/field_type.py @@ -1,69 +1,22 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class FieldType(str, enum.Enum): - """ - Choose these appropriate field type for your collection data - """ - - PLAIN_TEXT = "PlainText" - RICH_TEXT = "RichText" - IMAGE = "Image" - MULTI_IMAGE = "MultiImage" - VIDEO = "Video" - LINK = "Link" - EMAIL = "Email" - PHONE = "Phone" - NUMBER = "Number" - DATE_TIME = "DateTime" - SWITCH = "Switch" - COLOR = "Color" - EXT_FILE_REF = "ExtFileRef" - - def visit( - self, - plain_text: typing.Callable[[], T_Result], - rich_text: typing.Callable[[], T_Result], - image: typing.Callable[[], T_Result], - multi_image: typing.Callable[[], T_Result], - video: typing.Callable[[], T_Result], - link: typing.Callable[[], T_Result], - email: typing.Callable[[], T_Result], - phone: typing.Callable[[], T_Result], - number: typing.Callable[[], T_Result], - date_time: typing.Callable[[], T_Result], - switch: typing.Callable[[], T_Result], - color: typing.Callable[[], T_Result], - ext_file_ref: typing.Callable[[], T_Result], - ) -> T_Result: - if self is FieldType.PLAIN_TEXT: - return plain_text() - if self is FieldType.RICH_TEXT: - return rich_text() - if self is FieldType.IMAGE: - return image() - if self is FieldType.MULTI_IMAGE: - return multi_image() - if self is FieldType.VIDEO: - return video() - if self is FieldType.LINK: - return link() - if self is FieldType.EMAIL: - return email() - if self is FieldType.PHONE: - return phone() - if self is FieldType.NUMBER: - return number() - if self is FieldType.DATE_TIME: - return date_time() - if self is FieldType.SWITCH: - return switch() - if self is FieldType.COLOR: - return color() - if self is FieldType.EXT_FILE_REF: - return ext_file_ref() +FieldType = typing.Union[ + typing.Literal[ + "Color", + "DateTime", + "Email", + "ExtFileRef", + "Image", + "Link", + "MultiImage", + "Number", + "Phone", + "PlainText", + "RichText", + "Switch", + "Video", + ], + typing.Any, +] diff --git a/src/webflow/types/forbidden_error_body.py b/src/webflow/types/forbidden_error_body.py index 7f36dc7..f580ad2 100644 --- a/src/webflow/types/forbidden_error_body.py +++ b/src/webflow/types/forbidden_error_body.py @@ -1,35 +1,7 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt import typing +from .invalid_scopes import InvalidScopes +from .users_not_enabled import UsersNotEnabled -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - - -class ForbiddenErrorBody(pydantic_v1.BaseModel): - status: typing.Optional[int] = None - message: typing.Optional[str] = None - public_error_code: typing.Optional[str] = pydantic_v1.Field(alias="publicErrorCode", default=None) - external_reference: typing.Optional[str] = pydantic_v1.Field(alias="externalReference", default=None) - details: typing.Optional[typing.List[str]] = None - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} +ForbiddenErrorBody = typing.Union[InvalidScopes, UsersNotEnabled] diff --git a/src/webflow/types/form.py b/src/webflow/types/form.py index ae2a5e7..0cfef8b 100644 --- a/src/webflow/types/form.py +++ b/src/webflow/types/form.py @@ -1,90 +1,106 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from ..core.serialization import FieldMetadata +import pydantic +import datetime as dt from .form_field import FormField from .form_response_settings import FormResponseSettings +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Form(pydantic_v1.BaseModel): +class Form(UniversalBaseModel): """ A Webflow form """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ The Form name displayed on the site """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ Date that the Form was created on """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ Date that the Form was last updated on """ - fields: typing.Optional[typing.List[FormField]] = pydantic_v1.Field(default=None) + fields: typing.Optional[FormField] = pydantic.Field(default=None) """ - A list of form fields + A collection of form field objects """ - response_settings: typing.Optional[FormResponseSettings] = pydantic_v1.Field(alias="responseSettings", default=None) + response_settings: typing_extensions.Annotated[ + typing.Optional[FormResponseSettings], FieldMetadata(alias="responseSettings") + ] = pydantic.Field(default=None) """ Settings for form responses """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: typing.Optional[str] = pydantic.Field(default=None) """ - The unique id for the Form + The unique ID for the Form """ - site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) """ - The unique id of the Site the Form belongs to + The unique ID of the Site the Form belongs to """ - site_domain_id: typing.Optional[str] = pydantic_v1.Field(alias="siteDomainId", default=None) + site_domain_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteDomainId")] = ( + pydantic.Field(default=None) + ) """ - The unique id corresponding to the site's Domain name + The unique ID corresponding to the site's Domain name """ - page_id: typing.Optional[str] = pydantic_v1.Field(alias="pageId", default=None) + page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = pydantic.Field( + default=None + ) """ - The unique id for the Page on which the Form is placed + The unique ID for the Page on which the Form is placed """ - page_name: typing.Optional[str] = pydantic_v1.Field(alias="pageName", default=None) + page_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageName")] = pydantic.Field( + default=None + ) """ The user-visible name of the Page where the Form is placed """ - workspace_id: typing.Optional[str] = pydantic_v1.Field(alias="workspaceId", default=None) + form_element_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="formElementId")] = ( + pydantic.Field(default=None) + ) """ - The unique id of the Workspace the Site belongs to + The unique ID of the Form element """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( + pydantic.Field(default=None) + ) + """ + The unique ID of the Workspace the Site belongs to + """ - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_field.py b/src/webflow/types/form_field.py index f76bdcb..d62b01e 100644 --- a/src/webflow/types/form_field.py +++ b/src/webflow/types/form_field.py @@ -1,7 +1,6 @@ # This file was auto-generated by Fern from our API Definition. import typing - from .form_field_value import FormFieldValue FormField = typing.Dict[str, FormFieldValue] diff --git a/src/webflow/types/form_field_value.py b/src/webflow/types/form_field_value.py index 0a737ca..957624d 100644 --- a/src/webflow/types/form_field_value.py +++ b/src/webflow/types/form_field_value.py @@ -1,54 +1,48 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from ..core.serialization import FieldMetadata +import pydantic from .form_field_value_type import FormFieldValueType +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class FormFieldValue(pydantic_v1.BaseModel): +class FormFieldValue(UniversalBaseModel): """ An object containing field info for a specific fieldID. """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ The field name displayed on the site """ - type: typing.Optional[FormFieldValueType] = pydantic_v1.Field(default=None) + type: typing.Optional[FormFieldValueType] = pydantic.Field(default=None) """ The field type """ - placeholder: typing.Optional[str] = pydantic_v1.Field(default=None) + placeholder: typing.Optional[str] = pydantic.Field(default=None) """ The placeholder text for the field """ - user_visible: typing.Optional[bool] = pydantic_v1.Field(alias="userVisible", default=None) + user_visible: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="userVisible")] = ( + pydantic.Field(default=None) + ) """ Whether the field is visible to the user """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_field_value_type.py b/src/webflow/types/form_field_value_type.py index 97b8cae..d4d76d0 100644 --- a/src/webflow/types/form_field_value_type.py +++ b/src/webflow/types/form_field_value_type.py @@ -1,37 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class FormFieldValueType(str, enum.Enum): - """ - The field type - """ - - PLAIN = "Plain" - EMAIL = "Email" - PASSWORD = "Password" - PHONE = "Phone" - NUMBER = "Number" - - def visit( - self, - plain: typing.Callable[[], T_Result], - email: typing.Callable[[], T_Result], - password: typing.Callable[[], T_Result], - phone: typing.Callable[[], T_Result], - number: typing.Callable[[], T_Result], - ) -> T_Result: - if self is FormFieldValueType.PLAIN: - return plain() - if self is FormFieldValueType.EMAIL: - return email() - if self is FormFieldValueType.PASSWORD: - return password() - if self is FormFieldValueType.PHONE: - return phone() - if self is FormFieldValueType.NUMBER: - return number() +FormFieldValueType = typing.Union[typing.Literal["Plain", "Email", "Password", "Phone", "Number"], typing.Any] diff --git a/src/webflow/types/form_list.py b/src/webflow/types/form_list.py index 106dacd..17590c6 100644 --- a/src/webflow/types/form_list.py +++ b/src/webflow/types/form_list.py @@ -1,32 +1,22 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .form import Form from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class FormList(pydantic_v1.BaseModel): +class FormList(UniversalBaseModel): forms: typing.Optional[typing.List[Form]] = None pagination: typing.Optional[Pagination] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_response_settings.py b/src/webflow/types/form_response_settings.py index 2a652ab..c51d6b6 100644 --- a/src/webflow/types/form_response_settings.py +++ b/src/webflow/types/form_response_settings.py @@ -1,53 +1,51 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class FormResponseSettings(pydantic_v1.BaseModel): +class FormResponseSettings(UniversalBaseModel): """ Settings for form responses """ - redirect_url: typing.Optional[str] = pydantic_v1.Field(alias="redirectUrl", default=None) + redirect_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="redirectUrl")] = ( + pydantic.Field(default=None) + ) """ The url or path to redirect the user to after form submission """ - redirect_method: typing.Optional[str] = pydantic_v1.Field(alias="redirectMethod", default=None) + redirect_method: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="redirectMethod")] = ( + pydantic.Field(default=None) + ) """ The HTTP request method to use for the redirectUrl (eg. POST or GET) """ - redirect_action: typing.Optional[str] = pydantic_v1.Field(alias="redirectAction", default=None) + redirect_action: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="redirectAction")] = ( + pydantic.Field(default=None) + ) """ The action to take after form submission """ - send_email_confirmation: typing.Optional[bool] = pydantic_v1.Field(alias="sendEmailConfirmation", default=None) + send_email_confirmation: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="sendEmailConfirmation") + ] = pydantic.Field(default=None) """ Whether to send an email confirmation to the user """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_submission.py b/src/webflow/types/form_submission.py index e55cef3..cd18202 100644 --- a/src/webflow/types/form_submission.py +++ b/src/webflow/types/form_submission.py @@ -1,59 +1,60 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class FormSubmission(pydantic_v1.BaseModel): - id: typing.Optional[str] = pydantic_v1.Field(default=None) +class FormSubmission(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) """ - The unique id of the Form submission + The unique ID of the Form submission """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ The Form name displayed on the site """ - site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) """ - The unique id of the Site the Form belongs to + The unique ID of the Site the Form belongs to """ - workspace_id: typing.Optional[str] = pydantic_v1.Field(alias="workspaceId", default=None) + workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( + pydantic.Field(default=None) + ) """ - The unique id of the Workspace the Site belongs to + The unique ID of the Workspace the Site belongs to """ - date_submitted: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="dateSubmitted", default=None) + date_submitted: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="dateSubmitted")] = ( + pydantic.Field(default=None) + ) """ Date that the Form was submitted on """ - form_response: typing.Optional[typing.Dict[str, typing.Any]] = pydantic_v1.Field(alias="formResponse", default=None) + form_response: typing_extensions.Annotated[ + typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]], FieldMetadata(alias="formResponse") + ] = pydantic.Field(default=None) """ The data submitted in the Form """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_submission_list.py b/src/webflow/types/form_submission_list.py index 6222a6a..c9099a1 100644 --- a/src/webflow/types/form_submission_list.py +++ b/src/webflow/types/form_submission_list.py @@ -1,32 +1,26 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .form_submission import FormSubmission +from ..core.serialization import FieldMetadata from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class FormSubmissionList(pydantic_v1.BaseModel): - submissions: typing.Optional[typing.List[FormSubmission]] = None +class FormSubmissionList(UniversalBaseModel): + form_submissions: typing_extensions.Annotated[ + typing.Optional[typing.List[FormSubmission]], FieldMetadata(alias="formSubmissions") + ] = None pagination: typing.Optional[Pagination] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/image_node.py b/src/webflow/types/image_node.py index 89950bf..2351cea 100644 --- a/src/webflow/types/image_node.py +++ b/src/webflow/types/image_node.py @@ -1,36 +1,33 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +from .image_node_image import ImageNodeImage +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class ImageNode(pydantic_v1.BaseModel): +class ImageNode(UniversalBaseModel): """ Represents an image within the DOM. It contains details about the image, such as its alternative text (alt) for accessibility and an asset identifier for fetching the actual image resource. Additional attributes can be associated with the image for styling or other purposes. """ - alt: typing.Optional[str] = None - asset_id: typing.Optional[str] = pydantic_v1.Field(alias="assetId", default=None) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Node UUID + """ - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + image: typing.Optional[ImageNodeImage] = None + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + The custom attributes of the node + """ - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/image_node_image.py b/src/webflow/types/image_node_image.py new file mode 100644 index 0000000..2ef819f --- /dev/null +++ b/src/webflow/types/image_node_image.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ImageNodeImage(UniversalBaseModel): + alt: typing.Optional[str] = None + asset_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="assetId")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/invalid_domain.py b/src/webflow/types/invalid_domain.py index 304487f..60e64b7 100644 --- a/src/webflow/types/invalid_domain.py +++ b/src/webflow/types/invalid_domain.py @@ -2,4 +2,4 @@ import typing -InvalidDomain = typing.Any +InvalidDomain = typing.Optional[typing.Any] diff --git a/src/webflow/types/error_details_item.py b/src/webflow/types/invalid_scopes.py similarity index 54% rename from src/webflow/types/error_details_item.py rename to src/webflow/types/invalid_scopes.py index 693e235..90edaa0 100644 --- a/src/webflow/types/error_details_item.py +++ b/src/webflow/types/invalid_scopes.py @@ -2,4 +2,4 @@ import typing -ErrorDetailsItem = typing.Union[str, typing.Dict[str, typing.Any]] +InvalidScopes = typing.Optional[typing.Any] diff --git a/src/webflow/types/inventory_item.py b/src/webflow/types/inventory_item.py index 6032815..3eda2d3 100644 --- a/src/webflow/types/inventory_item.py +++ b/src/webflow/types/inventory_item.py @@ -1,49 +1,41 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions from .inventory_item_inventory_type import InventoryItemInventoryType +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class InventoryItem(pydantic_v1.BaseModel): +class InventoryItem(UniversalBaseModel): """ The availabile inventory for an item """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for a SKU item """ - quantity: typing.Optional[float] = pydantic_v1.Field(default=None) + quantity: typing.Optional[float] = pydantic.Field(default=None) """ Total quantity of items remaining in inventory (if inventoryType is finite) """ - inventory_type: typing.Optional[InventoryItemInventoryType] = pydantic_v1.Field(alias="inventoryType", default=None) + inventory_type: typing_extensions.Annotated[ + typing.Optional[InventoryItemInventoryType], FieldMetadata(alias="inventoryType") + ] = pydantic.Field(default=None) """ infinite or finite """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/inventory_item_inventory_type.py b/src/webflow/types/inventory_item_inventory_type.py index a781e0c..bd5afd2 100644 --- a/src/webflow/types/inventory_item_inventory_type.py +++ b/src/webflow/types/inventory_item_inventory_type.py @@ -1,21 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class InventoryItemInventoryType(str, enum.Enum): - """ - infinite or finite - """ - - INFINITE = "infinite" - FINITE = "finite" - - def visit(self, infinite: typing.Callable[[], T_Result], finite: typing.Callable[[], T_Result]) -> T_Result: - if self is InventoryItemInventoryType.INFINITE: - return infinite() - if self is InventoryItemInventoryType.FINITE: - return finite() +InventoryItemInventoryType = typing.Union[typing.Literal["infinite", "finite"], typing.Any] diff --git a/src/webflow/types/list_custom_code_blocks.py b/src/webflow/types/list_custom_code_blocks.py index a67223a..417c456 100644 --- a/src/webflow/types/list_custom_code_blocks.py +++ b/src/webflow/types/list_custom_code_blocks.py @@ -1,15 +1,14 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .custom_code_block import CustomCodeBlock from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class ListCustomCodeBlocks(pydantic_v1.BaseModel): +class ListCustomCodeBlocks(UniversalBaseModel): """ Custom Code Blocks corresponding to where scripts were applied """ @@ -17,20 +16,11 @@ class ListCustomCodeBlocks(pydantic_v1.BaseModel): blocks: typing.Optional[typing.List[CustomCodeBlock]] = None pagination: typing.Optional[Pagination] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/locale.py b/src/webflow/types/locale.py index 7989af3..ba88d45 100644 --- a/src/webflow/types/locale.py +++ b/src/webflow/types/locale.py @@ -1,69 +1,65 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class Locale(pydantic_v1.BaseModel): - id: typing.Optional[str] = pydantic_v1.Field(default=None) +class Locale(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) """ The unique identifier for the locale. """ - cms_locale_id: typing.Optional[str] = pydantic_v1.Field(alias="cmsLocaleId", default=None) + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) """ A CMS-specific identifier for the locale. """ - enabled: typing.Optional[bool] = pydantic_v1.Field(default=None) + enabled: typing.Optional[bool] = pydantic.Field(default=None) """ Indicates if the locale is enabled. """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ The display name of the locale, typically in English. """ - display_image_id: typing.Optional[str] = pydantic_v1.Field(alias="displayImageId", default=None) + display_image_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayImageId")] = ( + pydantic.Field(default=None) + ) """ An optional ID for an image associated with the locale, nullable. """ - redirect: typing.Optional[bool] = pydantic_v1.Field(default=None) + redirect: typing.Optional[bool] = pydantic.Field(default=None) """ Determines if requests should redirect to the locale's subdirectory. """ - subdirectory: typing.Optional[str] = pydantic_v1.Field(default=None) + subdirectory: typing.Optional[str] = pydantic.Field(default=None) """ The subdirectory path for the locale, used in URLs. """ - tag: typing.Optional[str] = pydantic_v1.Field(default=None) + tag: typing.Optional[str] = pydantic.Field(default=None) """ A tag or code representing the locale, often following a standard format like 'en-US'. """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/locales.py b/src/webflow/types/locales.py index de37c9b..7dad886 100644 --- a/src/webflow/types/locales.py +++ b/src/webflow/types/locales.py @@ -1,38 +1,28 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .locale import Locale +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Locales(pydantic_v1.BaseModel): - primary: typing.Optional[Locale] = pydantic_v1.Field(default=None) +class Locales(UniversalBaseModel): + primary: typing.Optional[Locale] = pydantic.Field(default=None) """ The primary locale for the site or application. """ - secondary: typing.Optional[typing.List[Locale]] = pydantic_v1.Field(default=None) + secondary: typing.Optional[typing.List[Locale]] = pydantic.Field(default=None) """ A list of secondary locales available for the site or application. """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/no_domains.py b/src/webflow/types/no_domains.py index c9162ec..714031f 100644 --- a/src/webflow/types/no_domains.py +++ b/src/webflow/types/no_domains.py @@ -2,4 +2,4 @@ import typing -NoDomains = typing.Any +NoDomains = typing.Optional[typing.Any] diff --git a/src/webflow/types/node.py b/src/webflow/types/node.py index 66370b4..cd0942f 100644 --- a/src/webflow/types/node.py +++ b/src/webflow/types/node.py @@ -1,47 +1,77 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from __future__ import annotations +from ..core.pydantic_utilities import UniversalBaseModel import typing +from .text_node_text import TextNodeText +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic +from .image_node_image import ImageNodeImage +import typing_extensions +from ..core.serialization import FieldMetadata +from .component_property import ComponentProperty -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -from .image_node import ImageNode -from .node_type import NodeType -from .text_node import TextNode - -class Node(pydantic_v1.BaseModel): +class Node_Text(UniversalBaseModel): """ A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + type: typing.Literal["text"] = "text" + id: typing.Optional[str] = None + text: typing.Optional[TextNodeText] = None + attributes: typing.Optional[typing.Dict[str, str]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class Node_Image(UniversalBaseModel): """ - Node UUID + A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. """ - type: typing.Optional[NodeType] = None - text: typing.Optional[TextNode] = None - image: typing.Optional[ImageNode] = None - attributes: typing.Optional[typing.Dict[str, str]] = pydantic_v1.Field(default=None) + type: typing.Literal["image"] = "image" + id: typing.Optional[str] = None + image: typing.Optional[ImageNodeImage] = None + attributes: typing.Optional[typing.Dict[str, str]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class Node_ComponentInstance(UniversalBaseModel): """ - The custom attributes of the node + A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) + type: typing.Literal["component-instance"] = "component-instance" + id: typing.Optional[str] = None + component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = None + property_overrides: typing_extensions.Annotated[ + typing.Optional[typing.List[ComponentProperty]], FieldMetadata(alias="propertyOverrides") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} +Node = typing.Union[Node_Text, Node_Image, Node_ComponentInstance] diff --git a/src/webflow/types/node_type.py b/src/webflow/types/node_type.py deleted file mode 100644 index 943719c..0000000 --- a/src/webflow/types/node_type.py +++ /dev/null @@ -1,17 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import enum -import typing - -T_Result = typing.TypeVar("T_Result") - - -class NodeType(str, enum.Enum): - TEXT = "text" - IMAGE = "image" - - def visit(self, text: typing.Callable[[], T_Result], image: typing.Callable[[], T_Result]) -> T_Result: - if self is NodeType.TEXT: - return text() - if self is NodeType.IMAGE: - return image() diff --git a/src/webflow/types/not_enterprise_plan_site.py b/src/webflow/types/not_enterprise_plan_site.py index 41410c6..87003ce 100644 --- a/src/webflow/types/not_enterprise_plan_site.py +++ b/src/webflow/types/not_enterprise_plan_site.py @@ -1,5 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .error import Error +import typing -NotEnterprisePlanSite = Error +NotEnterprisePlanSite = typing.Optional[typing.Any] diff --git a/src/webflow/types/not_enterprise_plan_workspace.py b/src/webflow/types/not_enterprise_plan_workspace.py new file mode 100644 index 0000000..e093b54 --- /dev/null +++ b/src/webflow/types/not_enterprise_plan_workspace.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +NotEnterprisePlanWorkspace = typing.Optional[typing.Any] diff --git a/src/webflow/types/oauth_scope.py b/src/webflow/types/oauth_scope.py deleted file mode 100644 index 59ad0fd..0000000 --- a/src/webflow/types/oauth_scope.py +++ /dev/null @@ -1,172 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import enum -import typing - -T_Result = typing.TypeVar("T_Result") - - -class OauthScope(str, enum.Enum): - AUTHORIZED_USER_READ = "authorized_user:read" - """ - read details about the authorized user - """ - - ASSETS_READ = "assets:read" - """ - read assets on the site - """ - - ASSETS_WRITE = "assets:write" - """ - write assets on a site - """ - - CMS_READ = "cms:read" - """ - read collections and items for a site - """ - - CMS_WRITE = "cms:write" - """ - write to collections and items for a site - """ - - CUSTOM_CODE_READ = "custom_code:read" - """ - read custom code on the site - """ - - CUSTOM_CODE_WRITE = "custom_code:write" - """ - modify custom code on the site - """ - - ECOMMERCE_READ = "ecommerce:read" - """ - read ecommerce data - """ - - ECOMMERCE_WRITE = "ecommerce:write" - """ - edit ecommerce data - """ - - FORMS_READ = "forms:read" - """ - read form data - """ - - FORMS_WRITE = "forms:write" - """ - write form data - """ - - PAGES_READ = "pages:read" - """ - read pages on the site - """ - - PAGES_WRITE = "pages:write" - """ - write to pages on the site - """ - - SITES_READ = "sites:read" - """ - read sites on the site - """ - - SITES_WRITE = "sites:write" - """ - modify pages on the site - """ - - USERS_READ = "users:read" - """ - read users on the site - """ - - SITE_ACTIVITY_READ = "site_activity:read" - """ - read site activity logs - """ - - USERS_WRITE = "users:write" - """ - modify users on the site - """ - - WORKSPACE_READ = "workspace:read" - """ - read workspace resource data - """ - - WORKSPACE_WRITE = "workspace:write" - """ - write workspace resource data - """ - - def visit( - self, - authorized_user_read: typing.Callable[[], T_Result], - assets_read: typing.Callable[[], T_Result], - assets_write: typing.Callable[[], T_Result], - cms_read: typing.Callable[[], T_Result], - cms_write: typing.Callable[[], T_Result], - custom_code_read: typing.Callable[[], T_Result], - custom_code_write: typing.Callable[[], T_Result], - ecommerce_read: typing.Callable[[], T_Result], - ecommerce_write: typing.Callable[[], T_Result], - forms_read: typing.Callable[[], T_Result], - forms_write: typing.Callable[[], T_Result], - pages_read: typing.Callable[[], T_Result], - pages_write: typing.Callable[[], T_Result], - sites_read: typing.Callable[[], T_Result], - sites_write: typing.Callable[[], T_Result], - users_read: typing.Callable[[], T_Result], - site_activity_read: typing.Callable[[], T_Result], - users_write: typing.Callable[[], T_Result], - workspace_read: typing.Callable[[], T_Result], - workspace_write: typing.Callable[[], T_Result], - ) -> T_Result: - if self is OauthScope.AUTHORIZED_USER_READ: - return authorized_user_read() - if self is OauthScope.ASSETS_READ: - return assets_read() - if self is OauthScope.ASSETS_WRITE: - return assets_write() - if self is OauthScope.CMS_READ: - return cms_read() - if self is OauthScope.CMS_WRITE: - return cms_write() - if self is OauthScope.CUSTOM_CODE_READ: - return custom_code_read() - if self is OauthScope.CUSTOM_CODE_WRITE: - return custom_code_write() - if self is OauthScope.ECOMMERCE_READ: - return ecommerce_read() - if self is OauthScope.ECOMMERCE_WRITE: - return ecommerce_write() - if self is OauthScope.FORMS_READ: - return forms_read() - if self is OauthScope.FORMS_WRITE: - return forms_write() - if self is OauthScope.PAGES_READ: - return pages_read() - if self is OauthScope.PAGES_WRITE: - return pages_write() - if self is OauthScope.SITES_READ: - return sites_read() - if self is OauthScope.SITES_WRITE: - return sites_write() - if self is OauthScope.USERS_READ: - return users_read() - if self is OauthScope.SITE_ACTIVITY_READ: - return site_activity_read() - if self is OauthScope.USERS_WRITE: - return users_write() - if self is OauthScope.WORKSPACE_READ: - return workspace_read() - if self is OauthScope.WORKSPACE_WRITE: - return workspace_write() diff --git a/src/webflow/types/order.py b/src/webflow/types/order.py index f4be90d..d45b1de 100644 --- a/src/webflow/types/order.py +++ b/src/webflow/types/order.py @@ -1,194 +1,235 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -from .order_address import OrderAddress -from .order_customer_info import OrderCustomerInfo +from ..core.serialization import FieldMetadata +import pydantic +from .order_status import OrderStatus +import datetime as dt from .order_dispute_last_status import OrderDisputeLastStatus -from .order_download_files_item import OrderDownloadFilesItem -from .order_metadata import OrderMetadata from .order_price import OrderPrice +from .order_address import OrderAddress +from .order_customer_info import OrderCustomerInfo from .order_purchased_item import OrderPurchasedItem -from .order_status import OrderStatus -from .order_totals import OrderTotals -from .paypal_details import PaypalDetails -from .stripe_card import StripeCard from .stripe_details import StripeDetails +from .stripe_card import StripeCard +from .paypal_details import PaypalDetails +from .order_metadata import OrderMetadata +from .order_totals import OrderTotals +from .order_download_files_item import OrderDownloadFilesItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Order(pydantic_v1.BaseModel): - order_id: typing.Optional[str] = pydantic_v1.Field(alias="orderId", default=None) +class Order(UniversalBaseModel): + order_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="orderId")] = pydantic.Field( + default=None + ) """ - The order id. Will usually be 6 hex characters, but can also be 9 hex characters if the site has a very large number of Orders. Randomly assigned. + The order ID. Will usually be 6 hex characters, but can also be 9 + hex characters if the site has a very large number of Orders. + Randomly assigned. """ - status: typing.Optional[OrderStatus] = pydantic_v1.Field(default=None) + status: typing.Optional[OrderStatus] = pydantic.Field(default=None) """ The status of the Order """ - comment: typing.Optional[str] = pydantic_v1.Field(default=None) + comment: typing.Optional[str] = pydantic.Field(default=None) """ A comment string for this Order, which is editable by API user (not used by Webflow). """ - order_comment: typing.Optional[str] = pydantic_v1.Field(alias="orderComment", default=None) + order_comment: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="orderComment")] = ( + pydantic.Field(default=None) + ) """ A comment that the customer left when making their Order """ - accepted_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="acceptedOn", default=None) + accepted_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="acceptedOn")] = ( + pydantic.Field(default=None) + ) """ The ISO8601 timestamp that an Order was placed. """ - fulfilled_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="fulfilledOn", default=None) + fulfilled_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="fulfilledOn")] = ( + pydantic.Field(default=None) + ) """ When an Order is marked as 'fulfilled', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. """ - refunded_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="refundedOn", default=None) + refunded_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="refundedOn")] = ( + pydantic.Field(default=None) + ) """ When an Order is marked as 'refunded', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. """ - disputed_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="disputedOn", default=None) + disputed_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="disputedOn")] = ( + pydantic.Field(default=None) + ) """ When an Order is marked as 'disputed', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. """ - dispute_updated_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="disputeUpdatedOn", default=None) + dispute_updated_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="disputeUpdatedOn") + ] = pydantic.Field(default=None) """ If an Order has been disputed by the customer, this key will be set to the ISO8601 timestamp of the last update received. If the Order is not disputed, the key will be null. """ - dispute_last_status: typing.Optional[OrderDisputeLastStatus] = pydantic_v1.Field( - alias="disputeLastStatus", default=None - ) + dispute_last_status: typing_extensions.Annotated[ + typing.Optional[OrderDisputeLastStatus], FieldMetadata(alias="disputeLastStatus") + ] = pydantic.Field(default=None) """ If an order was disputed by the customer, then this key will be set with the [dispute's status](https://stripe.com/docs/api#dispute_object-status). """ - customer_paid: typing.Optional[OrderPrice] = pydantic_v1.Field(alias="customerPaid", default=None) + customer_paid: typing_extensions.Annotated[typing.Optional[OrderPrice], FieldMetadata(alias="customerPaid")] = ( + pydantic.Field(default=None) + ) """ The total paid by the customer """ - net_amount: typing.Optional[OrderPrice] = pydantic_v1.Field(alias="netAmount", default=None) + net_amount: typing_extensions.Annotated[typing.Optional[OrderPrice], FieldMetadata(alias="netAmount")] = ( + pydantic.Field(default=None) + ) """ The net amount after application fees """ - application_fee: typing.Optional[OrderPrice] = pydantic_v1.Field(alias="applicationFee", default=None) + application_fee: typing_extensions.Annotated[typing.Optional[OrderPrice], FieldMetadata(alias="applicationFee")] = ( + pydantic.Field(default=None) + ) """ The application fee assessed by the platform """ - all_addresses: typing.Optional[typing.List[OrderAddress]] = pydantic_v1.Field(alias="allAddresses", default=None) + all_addresses: typing_extensions.Annotated[ + typing.Optional[typing.List[OrderAddress]], FieldMetadata(alias="allAddresses") + ] = pydantic.Field(default=None) """ All addresses provided by the customer during the ordering flow. """ - shipping_address: typing.Optional[OrderAddress] = pydantic_v1.Field(alias="shippingAddress", default=None) + shipping_address: typing_extensions.Annotated[ + typing.Optional[OrderAddress], FieldMetadata(alias="shippingAddress") + ] = pydantic.Field(default=None) """ The shipping address """ - billing_address: typing.Optional[OrderAddress] = pydantic_v1.Field(alias="billingAddress", default=None) + billing_address: typing_extensions.Annotated[ + typing.Optional[OrderAddress], FieldMetadata(alias="billingAddress") + ] = pydantic.Field(default=None) """ The billing address """ - shipping_provider: typing.Optional[str] = pydantic_v1.Field(alias="shippingProvider", default=None) + shipping_provider: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="shippingProvider")] = ( + pydantic.Field(default=None) + ) """ A string editable by the API user to note the shipping provider used (not used by Webflow). """ - shipping_tracking: typing.Optional[str] = pydantic_v1.Field(alias="shippingTracking", default=None) + shipping_tracking: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="shippingTracking")] = ( + pydantic.Field(default=None) + ) """ A string editable by the API user to note the shipping tracking number for the order (not used by Webflow). """ - shipping_tracking_url: typing.Optional[str] = pydantic_v1.Field(alias="shippingTrackingURL", default=None) - customer_info: typing.Optional[OrderCustomerInfo] = pydantic_v1.Field(alias="customerInfo", default=None) + shipping_tracking_url: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="shippingTrackingURL") + ] = None + customer_info: typing_extensions.Annotated[ + typing.Optional[OrderCustomerInfo], FieldMetadata(alias="customerInfo") + ] = pydantic.Field(default=None) """ An object with the keys `fullName` and `email`. """ - purchased_items: typing.Optional[typing.List[OrderPurchasedItem]] = pydantic_v1.Field( - alias="purchasedItems", default=None - ) + purchased_items: typing_extensions.Annotated[ + typing.Optional[typing.List[OrderPurchasedItem]], FieldMetadata(alias="purchasedItems") + ] = pydantic.Field(default=None) """ An array of all things that the Customer purchased. """ - purchased_items_count: typing.Optional[float] = pydantic_v1.Field(alias="purchasedItemsCount", default=None) + purchased_items_count: typing_extensions.Annotated[ + typing.Optional[float], FieldMetadata(alias="purchasedItemsCount") + ] = pydantic.Field(default=None) """ The sum of all 'count' fields in 'purchasedItems'. """ - stripe_details: typing.Optional[StripeDetails] = pydantic_v1.Field(alias="stripeDetails", default=None) - stripe_card: typing.Optional[StripeCard] = pydantic_v1.Field(alias="stripeCard", default=None) - paypal_details: typing.Optional[PaypalDetails] = pydantic_v1.Field(alias="paypalDetails", default=None) - custom_data: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = pydantic_v1.Field( - alias="customData", default=None - ) + stripe_details: typing_extensions.Annotated[ + typing.Optional[StripeDetails], FieldMetadata(alias="stripeDetails") + ] = None + stripe_card: typing_extensions.Annotated[typing.Optional[StripeCard], FieldMetadata(alias="stripeCard")] = None + paypal_details: typing_extensions.Annotated[ + typing.Optional[PaypalDetails], FieldMetadata(alias="paypalDetails") + ] = None + custom_data: typing_extensions.Annotated[ + typing.Optional[typing.List[typing.Dict[str, typing.Optional[typing.Any]]]], FieldMetadata(alias="customData") + ] = pydantic.Field(default=None) """ An array of additional inputs for custom order data gathering. Each object in the array represents an input with a name, and a textInput, textArea, or checkbox value. """ metadata: typing.Optional[OrderMetadata] = None - is_customer_deleted: typing.Optional[bool] = pydantic_v1.Field(alias="isCustomerDeleted", default=None) + is_customer_deleted: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="isCustomerDeleted") + ] = pydantic.Field(default=None) """ A boolean indicating whether the customer has been deleted from the site. """ - is_shipping_required: typing.Optional[bool] = pydantic_v1.Field(alias="isShippingRequired", default=None) + is_shipping_required: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="isShippingRequired") + ] = pydantic.Field(default=None) """ A boolean indicating whether the order contains one or more purchased items that require shipping. """ - has_downloads: typing.Optional[bool] = pydantic_v1.Field(alias="hasDownloads", default=None) + has_downloads: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="hasDownloads")] = ( + pydantic.Field(default=None) + ) """ A boolean indicating whether the order contains one or more purchased items that are downloadable. """ - payment_processor: typing.Optional[str] = pydantic_v1.Field(alias="paymentProcessor", default=None) + payment_processor: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="paymentProcessor")] = ( + pydantic.Field(default=None) + ) """ A string indicating the payment processor used for this order. """ - totals: typing.Optional[OrderTotals] = pydantic_v1.Field(default=None) + totals: typing.Optional[OrderTotals] = pydantic.Field(default=None) """ An object describing various pricing totals """ - download_files: typing.Optional[typing.List[OrderDownloadFilesItem]] = pydantic_v1.Field( - alias="downloadFiles", default=None - ) + download_files: typing_extensions.Annotated[ + typing.Optional[typing.List[OrderDownloadFilesItem]], FieldMetadata(alias="downloadFiles") + ] = pydantic.Field(default=None) """ An array of downloadable file objects. """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_address.py b/src/webflow/types/order_address.py index 5e7ec60..f225bc3 100644 --- a/src/webflow/types/order_address.py +++ b/src/webflow/types/order_address.py @@ -1,80 +1,78 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -from .order_address_japan_type import OrderAddressJapanType from .order_address_type import OrderAddressType +import pydantic +import typing_extensions +from .order_address_japan_type import OrderAddressJapanType +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class OrderAddress(pydantic_v1.BaseModel): +class OrderAddress(UniversalBaseModel): """ A customer address """ - type: typing.Optional[OrderAddressType] = pydantic_v1.Field(default=None) + type: typing.Optional[OrderAddressType] = pydantic.Field(default=None) """ The type of the order address (billing or shipping) """ - japan_type: typing.Optional[OrderAddressJapanType] = pydantic_v1.Field(alias="japanType", default=None) + japan_type: typing_extensions.Annotated[ + typing.Optional[OrderAddressJapanType], FieldMetadata(alias="japanType") + ] = pydantic.Field(default=None) """ Represents a Japan-only address format. This field will only appear on orders placed from Japan. """ - addressee: typing.Optional[str] = pydantic_v1.Field(default=None) + addressee: typing.Optional[str] = pydantic.Field(default=None) """ Display name on the address """ - line_1: typing.Optional[str] = pydantic_v1.Field(alias="line1", default=None) + line_1: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line1")] = pydantic.Field( + default=None + ) """ The first line of the address """ - line_2: typing.Optional[str] = pydantic_v1.Field(alias="line2", default=None) + line_2: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line2")] = pydantic.Field( + default=None + ) """ The second line of the address """ - city: typing.Optional[str] = pydantic_v1.Field(default=None) + city: typing.Optional[str] = pydantic.Field(default=None) """ The city of the address. """ - state: typing.Optional[str] = pydantic_v1.Field(default=None) + state: typing.Optional[str] = pydantic.Field(default=None) """ The state or province of the address """ - country: typing.Optional[str] = pydantic_v1.Field(default=None) + country: typing.Optional[str] = pydantic.Field(default=None) """ The country of the address """ - postal_code: typing.Optional[str] = pydantic_v1.Field(alias="postalCode", default=None) + postal_code: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="postalCode")] = pydantic.Field( + default=None + ) """ The postal code of the address """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_address_japan_type.py b/src/webflow/types/order_address_japan_type.py index 648e1a4..f3f1936 100644 --- a/src/webflow/types/order_address_japan_type.py +++ b/src/webflow/types/order_address_japan_type.py @@ -1,21 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class OrderAddressJapanType(str, enum.Enum): - """ - Represents a Japan-only address format. This field will only appear on orders placed from Japan. - """ - - KANA = "kana" - KANJI = "kanji" - - def visit(self, kana: typing.Callable[[], T_Result], kanji: typing.Callable[[], T_Result]) -> T_Result: - if self is OrderAddressJapanType.KANA: - return kana() - if self is OrderAddressJapanType.KANJI: - return kanji() +OrderAddressJapanType = typing.Union[typing.Literal["kana", "kanji"], typing.Any] diff --git a/src/webflow/types/order_address_type.py b/src/webflow/types/order_address_type.py index c54193a..a53b554 100644 --- a/src/webflow/types/order_address_type.py +++ b/src/webflow/types/order_address_type.py @@ -1,21 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class OrderAddressType(str, enum.Enum): - """ - The type of the order address (billing or shipping) - """ - - SHIPPING = "shipping" - BILLING = "billing" - - def visit(self, shipping: typing.Callable[[], T_Result], billing: typing.Callable[[], T_Result]) -> T_Result: - if self is OrderAddressType.SHIPPING: - return shipping() - if self is OrderAddressType.BILLING: - return billing() +OrderAddressType = typing.Union[typing.Literal["shipping", "billing"], typing.Any] diff --git a/src/webflow/types/order_customer_info.py b/src/webflow/types/order_customer_info.py index 1527e4a..2179d43 100644 --- a/src/webflow/types/order_customer_info.py +++ b/src/webflow/types/order_customer_info.py @@ -1,43 +1,35 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class OrderCustomerInfo(pydantic_v1.BaseModel): +class OrderCustomerInfo(UniversalBaseModel): """ An object with the keys `fullName` and `email`. """ - full_name: typing.Optional[str] = pydantic_v1.Field(alias="fullName", default=None) + full_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="fullName")] = pydantic.Field( + default=None + ) """ The full name of the Customer """ - email: typing.Optional[str] = pydantic_v1.Field(default=None) + email: typing.Optional[str] = pydantic.Field(default=None) """ The Customer's email address """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_dispute_last_status.py b/src/webflow/types/order_dispute_last_status.py index cc88362..16c3ae0 100644 --- a/src/webflow/types/order_dispute_last_status.py +++ b/src/webflow/types/order_dispute_last_status.py @@ -1,49 +1,17 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class OrderDisputeLastStatus(str, enum.Enum): - """ - If an order was disputed by the customer, then this key will be set with the [dispute's status](https://stripe.com/docs/api#dispute_object-status). - """ - - WARNING_NEEDS_RESPONSE = "warning_needs_response" - WARNING_UNDER_REVIEW = "warning_under_review" - WARNING_CLOSED = "warning_closed" - NEEDS_RESPONSE = "needs_response" - UNDER_REVIEW = "under_review" - CHARGE_REFUNDED = "charge_refunded" - WON = "won" - LOST = "lost" - - def visit( - self, - warning_needs_response: typing.Callable[[], T_Result], - warning_under_review: typing.Callable[[], T_Result], - warning_closed: typing.Callable[[], T_Result], - needs_response: typing.Callable[[], T_Result], - under_review: typing.Callable[[], T_Result], - charge_refunded: typing.Callable[[], T_Result], - won: typing.Callable[[], T_Result], - lost: typing.Callable[[], T_Result], - ) -> T_Result: - if self is OrderDisputeLastStatus.WARNING_NEEDS_RESPONSE: - return warning_needs_response() - if self is OrderDisputeLastStatus.WARNING_UNDER_REVIEW: - return warning_under_review() - if self is OrderDisputeLastStatus.WARNING_CLOSED: - return warning_closed() - if self is OrderDisputeLastStatus.NEEDS_RESPONSE: - return needs_response() - if self is OrderDisputeLastStatus.UNDER_REVIEW: - return under_review() - if self is OrderDisputeLastStatus.CHARGE_REFUNDED: - return charge_refunded() - if self is OrderDisputeLastStatus.WON: - return won() - if self is OrderDisputeLastStatus.LOST: - return lost() +OrderDisputeLastStatus = typing.Union[ + typing.Literal[ + "warning_needs_response", + "warning_under_review", + "warning_closed", + "needs_response", + "under_review", + "charge_refunded", + "won", + "lost", + ], + typing.Any, +] diff --git a/src/webflow/types/order_download_files_item.py b/src/webflow/types/order_download_files_item.py index e910b46..bb0b489 100644 --- a/src/webflow/types/order_download_files_item.py +++ b/src/webflow/types/order_download_files_item.py @@ -1,42 +1,32 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class OrderDownloadFilesItem(pydantic_v1.BaseModel): - id: typing.Optional[str] = pydantic_v1.Field(default=None) +class OrderDownloadFilesItem(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) """ The unique identifier for the downloadable file """ - name: typing.Optional[str] = pydantic_v1.Field(default=None) + name: typing.Optional[str] = pydantic.Field(default=None) """ The user-facing name for the downloadable file """ - url: typing.Optional[str] = pydantic_v1.Field(default=None) + url: typing.Optional[str] = pydantic.Field(default=None) """ The hosted location for the downloadable file """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_list.py b/src/webflow/types/order_list.py index fe867c8..7e01a45 100644 --- a/src/webflow/types/order_list.py +++ b/src/webflow/types/order_list.py @@ -1,40 +1,30 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .order import Order +import pydantic from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class OrderList(pydantic_v1.BaseModel): +class OrderList(UniversalBaseModel): """ Results from order list """ - orders: typing.Optional[typing.List[Order]] = pydantic_v1.Field(default=None) + orders: typing.Optional[typing.List[Order]] = pydantic.Field(default=None) """ List of orders """ pagination: typing.Optional[Pagination] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_metadata.py b/src/webflow/types/order_metadata.py index b1ebcd8..6b6de11 100644 --- a/src/webflow/types/order_metadata.py +++ b/src/webflow/types/order_metadata.py @@ -1,31 +1,21 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +class OrderMetadata(UniversalBaseModel): + is_buy_now: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isBuyNow")] = None -class OrderMetadata(pydantic_v1.BaseModel): - is_buy_now: typing.Optional[bool] = pydantic_v1.Field(alias="isBuyNow", default=None) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_price.py b/src/webflow/types/order_price.py index 28be474..6414850 100644 --- a/src/webflow/types/order_price.py +++ b/src/webflow/types/order_price.py @@ -1,42 +1,32 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class OrderPrice(pydantic_v1.BaseModel): - unit: typing.Optional[str] = pydantic_v1.Field(default=None) +class OrderPrice(UniversalBaseModel): + unit: typing.Optional[str] = pydantic.Field(default=None) """ The three-letter ISO currency code """ - value: typing.Optional[str] = pydantic_v1.Field(default=None) + value: typing.Optional[str] = pydantic.Field(default=None) """ The numeric value in the base unit of the currency """ - string: typing.Optional[str] = pydantic_v1.Field(default=None) + string: typing.Optional[str] = pydantic.Field(default=None) """ The user-facing string representation of the amount """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_purchased_item.py b/src/webflow/types/order_purchased_item.py index a35a732..ba51f76 100644 --- a/src/webflow/types/order_purchased_item.py +++ b/src/webflow/types/order_purchased_item.py @@ -1,108 +1,116 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions from .order_price import OrderPrice +from ..core.serialization import FieldMetadata from .order_purchased_item_variant_image import OrderPurchasedItemVariantImage +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class OrderPurchasedItem(pydantic_v1.BaseModel): +class OrderPurchasedItem(UniversalBaseModel): """ An Item that was purchased """ - count: typing.Optional[float] = pydantic_v1.Field(default=None) + count: typing.Optional[float] = pydantic.Field(default=None) """ Number of Item purchased. """ - row_total: typing.Optional[OrderPrice] = pydantic_v1.Field(alias="rowTotal", default=None) + row_total: typing_extensions.Annotated[typing.Optional[OrderPrice], FieldMetadata(alias="rowTotal")] = ( + pydantic.Field(default=None) + ) """ The total for the row """ - product_id: typing.Optional[str] = pydantic_v1.Field(alias="productId", default=None) + product_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="productId")] = pydantic.Field( + default=None + ) """ The unique identifier for the Product """ - product_name: typing.Optional[str] = pydantic_v1.Field(alias="productName", default=None) + product_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="productName")] = ( + pydantic.Field(default=None) + ) """ User-facing name of the Product """ - product_slug: typing.Optional[str] = pydantic_v1.Field(alias="productSlug", default=None) + product_slug: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="productSlug")] = ( + pydantic.Field(default=None) + ) """ Slug for the Product """ - variant_id: typing.Optional[str] = pydantic_v1.Field(alias="variantId", default=None) + variant_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="variantId")] = pydantic.Field( + default=None + ) """ Identifier for the Product Variant (SKU) """ - variant_name: typing.Optional[str] = pydantic_v1.Field(alias="variantName", default=None) + variant_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="variantName")] = ( + pydantic.Field(default=None) + ) """ User-facing name of the Product Variant (SKU) """ - variant_slug: typing.Optional[str] = pydantic_v1.Field(alias="variantSlug", default=None) + variant_slug: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="variantSlug")] = ( + pydantic.Field(default=None) + ) """ Slug for the Product Variant (SKU) """ - variant_sku: typing.Optional[str] = pydantic_v1.Field(alias="variantSKU", default=None) + variant_sku: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="variantSKU")] = pydantic.Field( + default=None + ) """ The user-defined custom SKU of the Product Variant (SKU) """ - variant_image: typing.Optional[OrderPurchasedItemVariantImage] = pydantic_v1.Field( - alias="variantImage", default=None + variant_image: typing_extensions.Annotated[ + typing.Optional[OrderPurchasedItemVariantImage], FieldMetadata(alias="variantImage") + ] = None + variant_price: typing_extensions.Annotated[typing.Optional[OrderPrice], FieldMetadata(alias="variantPrice")] = ( + pydantic.Field(default=None) ) - variant_price: typing.Optional[OrderPrice] = pydantic_v1.Field(alias="variantPrice", default=None) """ The price corresponding to the variant """ - weight: typing.Optional[float] = pydantic_v1.Field(default=None) + weight: typing.Optional[float] = pydantic.Field(default=None) """ The physical weight of the variant if provided, or null """ - width: typing.Optional[float] = pydantic_v1.Field(default=None) + width: typing.Optional[float] = pydantic.Field(default=None) """ The physical width of the variant if provided, or null """ - height: typing.Optional[float] = pydantic_v1.Field(default=None) + height: typing.Optional[float] = pydantic.Field(default=None) """ The physical height of the variant if provided, or null """ - length: typing.Optional[float] = pydantic_v1.Field(default=None) + length: typing.Optional[float] = pydantic.Field(default=None) """ The physical length of the variant if provided, or null """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_purchased_item_variant_image.py b/src/webflow/types/order_purchased_item_variant_image.py index 837ab2d..1444bdd 100644 --- a/src/webflow/types/order_purchased_item_variant_image.py +++ b/src/webflow/types/order_purchased_item_variant_image.py @@ -1,35 +1,25 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic from .order_purchased_item_variant_image_file import OrderPurchasedItemVariantImageFile +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class OrderPurchasedItemVariantImage(pydantic_v1.BaseModel): - url: typing.Optional[str] = pydantic_v1.Field(default=None) +class OrderPurchasedItemVariantImage(UniversalBaseModel): + url: typing.Optional[str] = pydantic.Field(default=None) """ The hosted location for the Variant's image """ file: typing.Optional[OrderPurchasedItemVariantImageFile] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_purchased_item_variant_image_file.py b/src/webflow/types/order_purchased_item_variant_image_file.py index b6c273f..e61c891 100644 --- a/src/webflow/types/order_purchased_item_variant_image_file.py +++ b/src/webflow/types/order_purchased_item_variant_image_file.py @@ -1,67 +1,64 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt from .order_purchased_item_variant_image_file_variants_item import OrderPurchasedItemVariantImageFileVariantsItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class OrderPurchasedItemVariantImageFile(pydantic_v1.BaseModel): - size: typing.Optional[float] = pydantic_v1.Field(default=None) +class OrderPurchasedItemVariantImageFile(UniversalBaseModel): + size: typing.Optional[float] = pydantic.Field(default=None) """ The image size in bytes """ - original_file_name: typing.Optional[str] = pydantic_v1.Field(alias="originalFileName", default=None) + original_file_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="originalFileName")] = ( + pydantic.Field(default=None) + ) """ the original name of the image """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ The creation timestamp of the image """ - content_type: typing.Optional[str] = pydantic_v1.Field(alias="contentType", default=None) + content_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="contentType")] = ( + pydantic.Field(default=None) + ) """ The MIME type of the image """ - width: typing.Optional[int] = pydantic_v1.Field(default=None) + width: typing.Optional[int] = pydantic.Field(default=None) """ The image width in pixels """ - height: typing.Optional[int] = pydantic_v1.Field(default=None) + height: typing.Optional[int] = pydantic.Field(default=None) """ The image height in pixels """ - variants: typing.Optional[typing.List[OrderPurchasedItemVariantImageFileVariantsItem]] = pydantic_v1.Field( + variants: typing.Optional[typing.List[OrderPurchasedItemVariantImageFileVariantsItem]] = pydantic.Field( default=None ) """ Variants of the supplied image """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py b/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py index 687898b..a49bb84 100644 --- a/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py +++ b/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py @@ -1,50 +1,42 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class OrderPurchasedItemVariantImageFileVariantsItem(pydantic_v1.BaseModel): - url: typing.Optional[str] = pydantic_v1.Field(default=None) +class OrderPurchasedItemVariantImageFileVariantsItem(UniversalBaseModel): + url: typing.Optional[str] = pydantic.Field(default=None) """ The hosted location for the Variant's image """ - original_file_name: typing.Optional[str] = pydantic_v1.Field(alias="originalFileName", default=None) - size: typing.Optional[float] = pydantic_v1.Field(default=None) + original_file_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="originalFileName")] = ( + None + ) + size: typing.Optional[float] = pydantic.Field(default=None) """ The image size in bytes """ - width: typing.Optional[int] = pydantic_v1.Field(default=None) + width: typing.Optional[int] = pydantic.Field(default=None) """ The image width in pixels """ - height: typing.Optional[int] = pydantic_v1.Field(default=None) + height: typing.Optional[int] = pydantic.Field(default=None) """ The image height in pixels """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_status.py b/src/webflow/types/order_status.py index 8db83e5..58e235c 100644 --- a/src/webflow/types/order_status.py +++ b/src/webflow/types/order_status.py @@ -1,41 +1,7 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class OrderStatus(str, enum.Enum): - """ - The status of the Order - """ - - PENDING = "pending" - UNFULFILLED = "unfulfilled" - FULFILLED = "fulfilled" - DISPUTED = "disputed" - DISPUTE_LOST = "dispute-lost" - REFUNDED = "refunded" - - def visit( - self, - pending: typing.Callable[[], T_Result], - unfulfilled: typing.Callable[[], T_Result], - fulfilled: typing.Callable[[], T_Result], - disputed: typing.Callable[[], T_Result], - dispute_lost: typing.Callable[[], T_Result], - refunded: typing.Callable[[], T_Result], - ) -> T_Result: - if self is OrderStatus.PENDING: - return pending() - if self is OrderStatus.UNFULFILLED: - return unfulfilled() - if self is OrderStatus.FULFILLED: - return fulfilled() - if self is OrderStatus.DISPUTED: - return disputed() - if self is OrderStatus.DISPUTE_LOST: - return dispute_lost() - if self is OrderStatus.REFUNDED: - return refunded() +OrderStatus = typing.Union[ + typing.Literal["pending", "unfulfilled", "fulfilled", "disputed", "dispute-lost", "refunded"], typing.Any +] diff --git a/src/webflow/types/order_totals.py b/src/webflow/types/order_totals.py index bed4a4f..3abdc2e 100644 --- a/src/webflow/types/order_totals.py +++ b/src/webflow/types/order_totals.py @@ -1,48 +1,38 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .order_price import OrderPrice +import pydantic from .order_totals_extras_item import OrderTotalsExtrasItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class OrderTotals(pydantic_v1.BaseModel): +class OrderTotals(UniversalBaseModel): """ An object describing various pricing totals """ - subtotal: typing.Optional[OrderPrice] = pydantic_v1.Field(default=None) + subtotal: typing.Optional[OrderPrice] = pydantic.Field(default=None) """ The subtotal price """ - extras: typing.Optional[typing.List[OrderTotalsExtrasItem]] = pydantic_v1.Field(default=None) + extras: typing.Optional[typing.List[OrderTotalsExtrasItem]] = pydantic.Field(default=None) """ An array of extra items, includes discounts, shipping, and taxes. """ - total: typing.Optional[OrderPrice] = pydantic_v1.Field(default=None) + total: typing.Optional[OrderPrice] = pydantic.Field(default=None) """ The total price """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_totals_extras_item.py b/src/webflow/types/order_totals_extras_item.py index 7c0b399..fa71f2f 100644 --- a/src/webflow/types/order_totals_extras_item.py +++ b/src/webflow/types/order_totals_extras_item.py @@ -1,53 +1,43 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -from .order_price import OrderPrice from .order_totals_extras_item_type import OrderTotalsExtrasItemType +import pydantic +from .order_price import OrderPrice +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class OrderTotalsExtrasItem(pydantic_v1.BaseModel): +class OrderTotalsExtrasItem(UniversalBaseModel): """ Extra order items, includes discounts, shipping, and taxes. """ - type: typing.Optional[OrderTotalsExtrasItemType] = pydantic_v1.Field(default=None) + type: typing.Optional[OrderTotalsExtrasItemType] = pydantic.Field(default=None) """ The type of extra item this is. """ - name: typing.Optional[str] = pydantic_v1.Field(default=None) + name: typing.Optional[str] = pydantic.Field(default=None) """ A human-readable (but English) name for this extra charge. """ - description: typing.Optional[str] = pydantic_v1.Field(default=None) + description: typing.Optional[str] = pydantic.Field(default=None) """ A human-readable (but English) description of this extra charge. """ - price: typing.Optional[OrderPrice] = pydantic_v1.Field(default=None) + price: typing.Optional[OrderPrice] = pydantic.Field(default=None) """ The price for the item """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_totals_extras_item_type.py b/src/webflow/types/order_totals_extras_item_type.py index 2ec3f09..34a8cb3 100644 --- a/src/webflow/types/order_totals_extras_item_type.py +++ b/src/webflow/types/order_totals_extras_item_type.py @@ -1,33 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class OrderTotalsExtrasItemType(str, enum.Enum): - """ - The type of extra item this is. - """ - - DISCOUNT = "discount" - DISCOUNT_SHIPPING = "discount-shipping" - SHIPPING = "shipping" - TAX = "tax" - - def visit( - self, - discount: typing.Callable[[], T_Result], - discount_shipping: typing.Callable[[], T_Result], - shipping: typing.Callable[[], T_Result], - tax: typing.Callable[[], T_Result], - ) -> T_Result: - if self is OrderTotalsExtrasItemType.DISCOUNT: - return discount() - if self is OrderTotalsExtrasItemType.DISCOUNT_SHIPPING: - return discount_shipping() - if self is OrderTotalsExtrasItemType.SHIPPING: - return shipping() - if self is OrderTotalsExtrasItemType.TAX: - return tax() +OrderTotalsExtrasItemType = typing.Union[typing.Literal["discount", "discount-shipping", "shipping", "tax"], typing.Any] diff --git a/src/webflow/types/page.py b/src/webflow/types/page.py index 4995ea4..56b32d3 100644 --- a/src/webflow/types/page.py +++ b/src/webflow/types/page.py @@ -1,105 +1,133 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -from .page_open_graph import PageOpenGraph +from ..core.serialization import FieldMetadata +import datetime as dt from .page_seo import PageSeo +from .page_open_graph import PageOpenGraph +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Page(pydantic_v1.BaseModel): +class Page(UniversalBaseModel): """ The Page object """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: str = pydantic.Field() """ Unique identifier for the Page """ - site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) """ Unique identifier for the Site """ - title: typing.Optional[str] = pydantic_v1.Field(default=None) + title: typing.Optional[str] = pydantic.Field(default=None) """ Title of the Page """ - slug: typing.Optional[str] = pydantic_v1.Field(default=None) + slug: typing.Optional[str] = pydantic.Field(default=None) """ slug of the Page (derived from title) """ - parent_id: typing.Optional[str] = pydantic_v1.Field(alias="parentId", default=None) + parent_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="parentId")] = pydantic.Field( + default=None + ) """ Identifier of the parent folder """ - collection_id: typing.Optional[str] = pydantic_v1.Field(alias="collectionId", default=None) + collection_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="collectionId")] = ( + pydantic.Field(default=None) + ) """ Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ The date the Page was created """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ The date the Page was most recently updated """ - archived: typing.Optional[bool] = pydantic_v1.Field(default=None) + archived: typing.Optional[bool] = pydantic.Field(default=None) """ Whether the Page has been archived """ - draft: typing.Optional[bool] = pydantic_v1.Field(default=None) + draft: typing.Optional[bool] = pydantic.Field(default=None) """ Whether the Page is a draft """ - can_branch: typing.Optional[bool] = pydantic_v1.Field(alias="canBranch", default=None) + can_branch: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="canBranch")] = pydantic.Field( + default=None + ) """ Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) """ - is_members_only: typing.Optional[bool] = pydantic_v1.Field(alias="isMembersOnly", default=None) + is_branch: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isBranch")] = pydantic.Field( + default=None + ) + """ + Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) + """ + + is_members_only: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isMembersOnly")] = ( + pydantic.Field(default=None) + ) """ Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) """ - seo: typing.Optional[PageSeo] = pydantic_v1.Field(default=None) + seo: typing.Optional[PageSeo] = pydantic.Field(default=None) """ SEO-related fields for the Page """ - open_graph: typing.Optional[PageOpenGraph] = pydantic_v1.Field(alias="openGraph", default=None) + open_graph: typing_extensions.Annotated[typing.Optional[PageOpenGraph], FieldMetadata(alias="openGraph")] = ( + pydantic.Field(default=None) + ) """ Open Graph fields for the Page """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) + locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="localeId")] = pydantic.Field( + default=None + ) + """ + Unique ID of the page locale + """ - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + published_path: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="publishedPath")] = ( + pydantic.Field(default=None) + ) + """ + Relative path of the published page URL + """ - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_details.py b/src/webflow/types/page_details.py deleted file mode 100644 index 6efa48e..0000000 --- a/src/webflow/types/page_details.py +++ /dev/null @@ -1,115 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -from .page_details_open_graph import PageDetailsOpenGraph -from .page_details_seo import PageDetailsSeo - - -class PageDetails(pydantic_v1.BaseModel): - """ - The Page object - """ - - id: typing.Optional[str] = pydantic_v1.Field(default=None) - """ - Unique identifier for the Page - """ - - site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) - """ - Unique identifier for the Site - """ - - title: typing.Optional[str] = pydantic_v1.Field(default=None) - """ - Title of the Page - """ - - slug: typing.Optional[str] = pydantic_v1.Field(default=None) - """ - slug of the Page (derived from title) - """ - - parent_id: typing.Optional[str] = pydantic_v1.Field(alias="parentId", default=None) - """ - Identifier of the parent folder - """ - - collection_id: typing.Optional[str] = pydantic_v1.Field(alias="collectionId", default=None) - """ - Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. - """ - - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) - """ - The date the Page was created - """ - - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) - """ - The date the Page was most recently updated - """ - - archived: typing.Optional[bool] = pydantic_v1.Field(default=None) - """ - Whether the Page has been archived - """ - - draft: typing.Optional[bool] = pydantic_v1.Field(default=None) - """ - Whether the Page is a draft - """ - - can_branch: typing.Optional[bool] = pydantic_v1.Field(alias="canBranch", default=None) - """ - Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) - """ - - is_members_only: typing.Optional[bool] = pydantic_v1.Field(alias="isMembersOnly", default=None) - """ - Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) - """ - - seo: typing.Optional[PageDetailsSeo] = pydantic_v1.Field(default=None) - """ - SEO-related fields for the Page - """ - - open_graph: typing.Optional[PageDetailsOpenGraph] = pydantic_v1.Field(alias="openGraph", default=None) - """ - Open Graph fields for the Page - """ - - locale_id: typing.Optional[str] = pydantic_v1.Field(alias="localeId", default=None) - """ - Unique ID of the page locale - """ - - published_path: typing.Optional[str] = pydantic_v1.Field(alias="publishedPath", default=None) - """ - Relative path of the published page URL - """ - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/page_details_open_graph.py b/src/webflow/types/page_details_open_graph.py deleted file mode 100644 index 6d82c28..0000000 --- a/src/webflow/types/page_details_open_graph.py +++ /dev/null @@ -1,53 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - - -class PageDetailsOpenGraph(pydantic_v1.BaseModel): - """ - Open Graph fields for the Page - """ - - title: typing.Optional[str] = pydantic_v1.Field(default=None) - """ - The title supplied to Open Graph annotations - """ - - title_copied: typing.Optional[bool] = pydantic_v1.Field(alias="titleCopied", default=None) - """ - Indicates the Open Graph title was copied from the SEO title - """ - - description: typing.Optional[str] = pydantic_v1.Field(default=None) - """ - The description supplied to Open Graph annotations - """ - - description_copied: typing.Optional[bool] = pydantic_v1.Field(alias="descriptionCopied", default=None) - """ - Indicates the Open Graph description was copied from the SEO description - """ - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/page_details_seo.py b/src/webflow/types/page_details_seo.py deleted file mode 100644 index 7038e39..0000000 --- a/src/webflow/types/page_details_seo.py +++ /dev/null @@ -1,41 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import datetime as dt -import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - - -class PageDetailsSeo(pydantic_v1.BaseModel): - """ - SEO-related fields for the Page - """ - - title: typing.Optional[str] = pydantic_v1.Field(default=None) - """ - The Page title shown in search engine results - """ - - description: typing.Optional[str] = pydantic_v1.Field(default=None) - """ - The Page description shown in search engine results - """ - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) - - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} diff --git a/src/webflow/types/page_list.py b/src/webflow/types/page_list.py index 11c5420..59e4e79 100644 --- a/src/webflow/types/page_list.py +++ b/src/webflow/types/page_list.py @@ -1,15 +1,14 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .page import Page from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class PageList(pydantic_v1.BaseModel): +class PageList(UniversalBaseModel): """ The Page object """ @@ -17,20 +16,11 @@ class PageList(pydantic_v1.BaseModel): pages: typing.Optional[typing.List[Page]] = None pagination: typing.Optional[Pagination] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_open_graph.py b/src/webflow/types/page_open_graph.py index 317ba4b..f6d48b1 100644 --- a/src/webflow/types/page_open_graph.py +++ b/src/webflow/types/page_open_graph.py @@ -1,53 +1,47 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class PageOpenGraph(pydantic_v1.BaseModel): +class PageOpenGraph(UniversalBaseModel): """ Open Graph fields for the Page """ - title: typing.Optional[str] = pydantic_v1.Field(default=None) + title: typing.Optional[str] = pydantic.Field(default=None) """ The title supplied to Open Graph annotations """ - title_copied: typing.Optional[bool] = pydantic_v1.Field(alias="titleCopied", default=None) + title_copied: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="titleCopied")] = ( + pydantic.Field(default=None) + ) """ Indicates the Open Graph title was copied from the SEO title """ - description: typing.Optional[str] = pydantic_v1.Field(default=None) + description: typing.Optional[str] = pydantic.Field(default=None) """ The description supplied to Open Graph annotations """ - description_copied: typing.Optional[bool] = pydantic_v1.Field(alias="descriptionCopied", default=None) + description_copied: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="descriptionCopied")] = ( + pydantic.Field(default=None) + ) """ Indicates the Open Graph description was copied from the SEO description """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_seo.py b/src/webflow/types/page_seo.py index 02a9d3e..737e68c 100644 --- a/src/webflow/types/page_seo.py +++ b/src/webflow/types/page_seo.py @@ -1,41 +1,31 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class PageSeo(pydantic_v1.BaseModel): +class PageSeo(UniversalBaseModel): """ SEO-related fields for the Page """ - title: typing.Optional[str] = pydantic_v1.Field(default=None) + title: typing.Optional[str] = pydantic.Field(default=None) """ The Page title shown in search engine results """ - description: typing.Optional[str] = pydantic_v1.Field(default=None) + description: typing.Optional[str] = pydantic.Field(default=None) """ The Page description shown in search engine results """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/pagination.py b/src/webflow/types/pagination.py index 16fed76..aa38c46 100644 --- a/src/webflow/types/pagination.py +++ b/src/webflow/types/pagination.py @@ -1,46 +1,36 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class Pagination(pydantic_v1.BaseModel): +class Pagination(UniversalBaseModel): """ Pagination object """ - limit: typing.Optional[float] = pydantic_v1.Field(default=None) + limit: typing.Optional[float] = pydantic.Field(default=None) """ The limit used for pagination """ - offset: typing.Optional[float] = pydantic_v1.Field(default=None) + offset: typing.Optional[float] = pydantic.Field(default=None) """ The offset used for pagination """ - total: typing.Optional[float] = pydantic_v1.Field(default=None) + total: typing.Optional[float] = pydantic.Field(default=None) """ The total number of records """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/paypal_details.py b/src/webflow/types/paypal_details.py index 3e8642c..b98efef 100644 --- a/src/webflow/types/paypal_details.py +++ b/src/webflow/types/paypal_details.py @@ -1,59 +1,61 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class PaypalDetails(pydantic_v1.BaseModel): - order_id: typing.Optional[str] = pydantic_v1.Field(alias="orderId", default=None) +class PaypalDetails(UniversalBaseModel): + order_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="orderId")] = pydantic.Field( + default=None + ) """ PayPal order identifier """ - payer_id: typing.Optional[str] = pydantic_v1.Field(alias="payerId", default=None) + payer_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="payerId")] = pydantic.Field( + default=None + ) """ PayPal payer identifier """ - capture_id: typing.Optional[str] = pydantic_v1.Field(alias="captureId", default=None) + capture_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="captureId")] = pydantic.Field( + default=None + ) """ PayPal capture identifier """ - refund_id: typing.Optional[str] = pydantic_v1.Field(alias="refundId", default=None) + refund_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="refundId")] = pydantic.Field( + default=None + ) """ PayPal refund identifier """ - refund_reason: typing.Optional[str] = pydantic_v1.Field(alias="refundReason", default=None) + refund_reason: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="refundReason")] = ( + pydantic.Field(default=None) + ) """ PayPal-issued reason for the refund """ - dispute_id: typing.Optional[str] = pydantic_v1.Field(alias="disputeId", default=None) + dispute_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="disputeId")] = pydantic.Field( + default=None + ) """ PayPal dispute identifier """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/product.py b/src/webflow/types/product.py index c557bd3..a39ca3d 100644 --- a/src/webflow/types/product.py +++ b/src/webflow/types/product.py @@ -1,71 +1,74 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt from .product_field_data import ProductFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Product(pydantic_v1.BaseModel): +class Product(UniversalBaseModel): """ The Product object """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for the Product """ - cms_locale_id: typing.Optional[str] = pydantic_v1.Field(alias="cmsLocaleId", default=None) + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) """ Identifier for the locale of the CMS item """ - last_published: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastPublished", default=None) + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + pydantic.Field(default=None) + ) """ The date the Product was last published """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ The date the Product was last updated """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ The date the Product was created """ - is_archived: typing.Optional[bool] = pydantic_v1.Field(alias="isArchived", default=None) + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( + default=None + ) """ Boolean determining if the Product is set to archived """ - is_draft: typing.Optional[bool] = pydantic_v1.Field(alias="isDraft", default=None) + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( + default=None + ) """ Boolean determining if the Product is set to draft """ - field_data: typing.Optional[ProductFieldData] = pydantic_v1.Field(alias="fieldData", default=None) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + field_data: typing_extensions.Annotated[typing.Optional[ProductFieldData], FieldMetadata(alias="fieldData")] = None - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/product_and_sk_us.py b/src/webflow/types/product_and_sk_us.py index eb9ab3d..6aea2cb 100644 --- a/src/webflow/types/product_and_sk_us.py +++ b/src/webflow/types/product_and_sk_us.py @@ -1,39 +1,29 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .product import Product from .sku import Sku +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class ProductAndSkUs(pydantic_v1.BaseModel): +class ProductAndSkUs(UniversalBaseModel): """ A product and its SKUs. """ product: typing.Optional[Product] = None - skus: typing.Optional[typing.List[Sku]] = pydantic_v1.Field(default=None) + skus: typing.Optional[typing.List[Sku]] = pydantic.Field(default=None) """ A list of SKU Objects """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/product_and_sk_us_list.py b/src/webflow/types/product_and_sk_us_list.py index db89130..6bdafd5 100644 --- a/src/webflow/types/product_and_sk_us_list.py +++ b/src/webflow/types/product_and_sk_us_list.py @@ -1,40 +1,30 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -from .pagination import Pagination from .product_and_sk_us import ProductAndSkUs +import pydantic +from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class ProductAndSkUsList(pydantic_v1.BaseModel): +class ProductAndSkUsList(UniversalBaseModel): """ Results from product list """ - items: typing.Optional[typing.List[ProductAndSkUs]] = pydantic_v1.Field(default=None) + items: typing.Optional[typing.List[ProductAndSkUs]] = pydantic.Field(default=None) """ List of Item objects within the Collection. Contains product and skus keys for each Item """ pagination: typing.Optional[Pagination] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/product_field_data.py b/src/webflow/types/product_field_data.py index ac2db70..e58b83d 100644 --- a/src/webflow/types/product_field_data.py +++ b/src/webflow/types/product_field_data.py @@ -1,85 +1,79 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -from .product_field_data_ec_product_type import ProductFieldDataEcProductType -from .product_field_data_tax_category import ProductFieldDataTaxCategory +import pydantic +import typing_extensions from .sku_property_list import SkuPropertyList +from ..core.serialization import FieldMetadata +from .product_field_data_tax_category import ProductFieldDataTaxCategory +from .product_field_data_ec_product_type import ProductFieldDataEcProductType +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class ProductFieldData(pydantic_v1.BaseModel): +class ProductFieldData(UniversalBaseModel): """ - Contains content-specific details for a product, covering both standard (e.g., title, description) and custom fields tailored to the product setup. + Contains content-specific details for a product, covering both standard (e.g., title, description) and custom fields tailored to the product setup. """ - name: typing.Optional[str] = pydantic_v1.Field(default=None) + name: typing.Optional[str] = pydantic.Field(default=None) """ Name of the Product """ - slug: typing.Optional[str] = pydantic_v1.Field(default=None) + slug: typing.Optional[str] = pydantic.Field(default=None) """ URL structure of the Product in your site. """ - description: typing.Optional[str] = pydantic_v1.Field(default=None) + description: typing.Optional[str] = pydantic.Field(default=None) """ A description of your product """ - shippable: typing.Optional[bool] = pydantic_v1.Field(default=None) + shippable: typing.Optional[bool] = pydantic.Field(default=None) """ Boolean determining if the Product is shippable """ - sku_properties: typing.Optional[typing.List[SkuPropertyList]] = pydantic_v1.Field( - alias="sku-properties", default=None - ) + sku_properties: typing_extensions.Annotated[ + typing.Optional[typing.List[SkuPropertyList]], FieldMetadata(alias="sku-properties") + ] = pydantic.Field(default=None) """ Variant types to include in SKUs """ - categories: typing.Optional[typing.List[str]] = pydantic_v1.Field(default=None) + categories: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ The categories your product belongs to. """ - tax_category: typing.Optional[ProductFieldDataTaxCategory] = pydantic_v1.Field(alias="tax-category", default=None) + tax_category: typing_extensions.Annotated[ + typing.Optional[ProductFieldDataTaxCategory], FieldMetadata(alias="tax-category") + ] = pydantic.Field(default=None) """ Product tax class """ - default_sku: typing.Optional[str] = pydantic_v1.Field(alias="default-sku", default=None) + default_sku: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="default-sku")] = pydantic.Field( + default=None + ) """ The default SKU associated with this product. """ - ec_product_type: typing.Optional[ProductFieldDataEcProductType] = pydantic_v1.Field( - alias="ec-product-type", default=None - ) + ec_product_type: typing_extensions.Annotated[ + typing.Optional[ProductFieldDataEcProductType], FieldMetadata(alias="ec-product-type") + ] = pydantic.Field(default=None) """ Product types. Enums reflect the following values in order: Physical, Digital, Service, Advanced" """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/product_field_data_ec_product_type.py b/src/webflow/types/product_field_data_ec_product_type.py index f496e5a..8a74a70 100644 --- a/src/webflow/types/product_field_data_ec_product_type.py +++ b/src/webflow/types/product_field_data_ec_product_type.py @@ -1,33 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class ProductFieldDataEcProductType(str, enum.Enum): - """ - Product types. Enums reflect the following values in order: Physical, Digital, Service, Advanced" - """ - - FF_42_FEE_0113744_F_693_A_764_E_3431_A_9_CC_2 = "ff42fee0113744f693a764e3431a9cc2" - F_22027_DB_68002190_AEF_89_A_4_A_2_B_7_AC_8_A_1 = "f22027db68002190aef89a4a2b7ac8a1" - C_599_E_43_B_1_A_1_C_34_D_5_A_323_AEDF_75_D_3_ADF_6 = "c599e43b1a1c34d5a323aedf75d3adf6" - B_6_CCC_1830_DB_4_B_1_BABEB_06_A_9_AC_5_F_6_DD_76 = "b6ccc1830db4b1babeb06a9ac5f6dd76" - - def visit( - self, - ff_42_fee_0113744_f_693_a_764_e_3431_a_9_cc_2: typing.Callable[[], T_Result], - f_22027_db_68002190_aef_89_a_4_a_2_b_7_ac_8_a_1: typing.Callable[[], T_Result], - c_599_e_43_b_1_a_1_c_34_d_5_a_323_aedf_75_d_3_adf_6: typing.Callable[[], T_Result], - b_6_ccc_1830_db_4_b_1_babeb_06_a_9_ac_5_f_6_dd_76: typing.Callable[[], T_Result], - ) -> T_Result: - if self is ProductFieldDataEcProductType.FF_42_FEE_0113744_F_693_A_764_E_3431_A_9_CC_2: - return ff_42_fee_0113744_f_693_a_764_e_3431_a_9_cc_2() - if self is ProductFieldDataEcProductType.F_22027_DB_68002190_AEF_89_A_4_A_2_B_7_AC_8_A_1: - return f_22027_db_68002190_aef_89_a_4_a_2_b_7_ac_8_a_1() - if self is ProductFieldDataEcProductType.C_599_E_43_B_1_A_1_C_34_D_5_A_323_AEDF_75_D_3_ADF_6: - return c_599_e_43_b_1_a_1_c_34_d_5_a_323_aedf_75_d_3_adf_6() - if self is ProductFieldDataEcProductType.B_6_CCC_1830_DB_4_B_1_BABEB_06_A_9_AC_5_F_6_DD_76: - return b_6_ccc_1830_db_4_b_1_babeb_06_a_9_ac_5_f_6_dd_76() +ProductFieldDataEcProductType = typing.Union[ + typing.Literal[ + "ff42fee0113744f693a764e3431a9cc2", + "f22027db68002190aef89a4a2b7ac8a1", + "c599e43b1a1c34d5a323aedf75d3adf6", + "b6ccc1830db4b1babeb06a9ac5f6dd76", + ], + typing.Any, +] diff --git a/src/webflow/types/product_field_data_tax_category.py b/src/webflow/types/product_field_data_tax_category.py index bb27b51..54de073 100644 --- a/src/webflow/types/product_field_data_tax_category.py +++ b/src/webflow/types/product_field_data_tax_category.py @@ -1,133 +1,38 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class ProductFieldDataTaxCategory(str, enum.Enum): - """ - Product tax class - """ - - STANDARD_TAXABLE = "standard-taxable" - STANDARD_EXEMPT = "standard-exempt" - BOOKS_RELIGIOUS = "books-religious" - BOOKS_TEXTBOOK = "books-textbook" - CLOTHING = "clothing" - CLOTHING_SWIMWEAR = "clothing-swimwear" - DIGITAL_GOODS = "digital-goods" - DIGITAL_SERVICE = "digital-service" - DRUGS_NON_PRESCRIPTION = "drugs-non-prescription" - DRUGS_PRESCRIPTION = "drugs-prescription" - FOOD_BOTTLED_WATER = "food-bottled-water" - FOOD_CANDY = "food-candy" - FOOD_GROCERIES = "food-groceries" - FOOD_PREPARED = "food-prepared" - FOOD_SODA = "food-soda" - FOOD_SUPPLEMENTS = "food-supplements" - MAGAZINE_INDIVIDUAL = "magazine-individual" - MAGAZINE_SUBSCRIPTION = "magazine-subscription" - SERVICE_ADMISSION = "service-admission" - SERVICE_ADVERTISING = "service-advertising" - SERVICE_DRY_CLEANING = "service-dry-cleaning" - SERVICE_HAIRDRESSING = "service-hairdressing" - SERVICE_INSTALLATION = "service-installation" - SERVICE_MISCELLANEOUS = "service-miscellaneous" - SERVICE_PARKING = "service-parking" - SERVICE_PRINTING = "service-printing" - SERVICE_PROFESSIONAL = "service-professional" - SERVICE_REPAIR = "service-repair" - SERVICE_TRAINING = "service-training" - - def visit( - self, - standard_taxable: typing.Callable[[], T_Result], - standard_exempt: typing.Callable[[], T_Result], - books_religious: typing.Callable[[], T_Result], - books_textbook: typing.Callable[[], T_Result], - clothing: typing.Callable[[], T_Result], - clothing_swimwear: typing.Callable[[], T_Result], - digital_goods: typing.Callable[[], T_Result], - digital_service: typing.Callable[[], T_Result], - drugs_non_prescription: typing.Callable[[], T_Result], - drugs_prescription: typing.Callable[[], T_Result], - food_bottled_water: typing.Callable[[], T_Result], - food_candy: typing.Callable[[], T_Result], - food_groceries: typing.Callable[[], T_Result], - food_prepared: typing.Callable[[], T_Result], - food_soda: typing.Callable[[], T_Result], - food_supplements: typing.Callable[[], T_Result], - magazine_individual: typing.Callable[[], T_Result], - magazine_subscription: typing.Callable[[], T_Result], - service_admission: typing.Callable[[], T_Result], - service_advertising: typing.Callable[[], T_Result], - service_dry_cleaning: typing.Callable[[], T_Result], - service_hairdressing: typing.Callable[[], T_Result], - service_installation: typing.Callable[[], T_Result], - service_miscellaneous: typing.Callable[[], T_Result], - service_parking: typing.Callable[[], T_Result], - service_printing: typing.Callable[[], T_Result], - service_professional: typing.Callable[[], T_Result], - service_repair: typing.Callable[[], T_Result], - service_training: typing.Callable[[], T_Result], - ) -> T_Result: - if self is ProductFieldDataTaxCategory.STANDARD_TAXABLE: - return standard_taxable() - if self is ProductFieldDataTaxCategory.STANDARD_EXEMPT: - return standard_exempt() - if self is ProductFieldDataTaxCategory.BOOKS_RELIGIOUS: - return books_religious() - if self is ProductFieldDataTaxCategory.BOOKS_TEXTBOOK: - return books_textbook() - if self is ProductFieldDataTaxCategory.CLOTHING: - return clothing() - if self is ProductFieldDataTaxCategory.CLOTHING_SWIMWEAR: - return clothing_swimwear() - if self is ProductFieldDataTaxCategory.DIGITAL_GOODS: - return digital_goods() - if self is ProductFieldDataTaxCategory.DIGITAL_SERVICE: - return digital_service() - if self is ProductFieldDataTaxCategory.DRUGS_NON_PRESCRIPTION: - return drugs_non_prescription() - if self is ProductFieldDataTaxCategory.DRUGS_PRESCRIPTION: - return drugs_prescription() - if self is ProductFieldDataTaxCategory.FOOD_BOTTLED_WATER: - return food_bottled_water() - if self is ProductFieldDataTaxCategory.FOOD_CANDY: - return food_candy() - if self is ProductFieldDataTaxCategory.FOOD_GROCERIES: - return food_groceries() - if self is ProductFieldDataTaxCategory.FOOD_PREPARED: - return food_prepared() - if self is ProductFieldDataTaxCategory.FOOD_SODA: - return food_soda() - if self is ProductFieldDataTaxCategory.FOOD_SUPPLEMENTS: - return food_supplements() - if self is ProductFieldDataTaxCategory.MAGAZINE_INDIVIDUAL: - return magazine_individual() - if self is ProductFieldDataTaxCategory.MAGAZINE_SUBSCRIPTION: - return magazine_subscription() - if self is ProductFieldDataTaxCategory.SERVICE_ADMISSION: - return service_admission() - if self is ProductFieldDataTaxCategory.SERVICE_ADVERTISING: - return service_advertising() - if self is ProductFieldDataTaxCategory.SERVICE_DRY_CLEANING: - return service_dry_cleaning() - if self is ProductFieldDataTaxCategory.SERVICE_HAIRDRESSING: - return service_hairdressing() - if self is ProductFieldDataTaxCategory.SERVICE_INSTALLATION: - return service_installation() - if self is ProductFieldDataTaxCategory.SERVICE_MISCELLANEOUS: - return service_miscellaneous() - if self is ProductFieldDataTaxCategory.SERVICE_PARKING: - return service_parking() - if self is ProductFieldDataTaxCategory.SERVICE_PRINTING: - return service_printing() - if self is ProductFieldDataTaxCategory.SERVICE_PROFESSIONAL: - return service_professional() - if self is ProductFieldDataTaxCategory.SERVICE_REPAIR: - return service_repair() - if self is ProductFieldDataTaxCategory.SERVICE_TRAINING: - return service_training() +ProductFieldDataTaxCategory = typing.Union[ + typing.Literal[ + "standard-taxable", + "standard-exempt", + "books-religious", + "books-textbook", + "clothing", + "clothing-swimwear", + "digital-goods", + "digital-service", + "drugs-non-prescription", + "drugs-prescription", + "food-bottled-water", + "food-candy", + "food-groceries", + "food-prepared", + "food-soda", + "food-supplements", + "magazine-individual", + "magazine-subscription", + "service-admission", + "service-advertising", + "service-dry-cleaning", + "service-hairdressing", + "service-installation", + "service-miscellaneous", + "service-parking", + "service-printing", + "service-professional", + "service-repair", + "service-training", + ], + typing.Any, +] diff --git a/src/webflow/types/publish_status.py b/src/webflow/types/publish_status.py index dbee8d9..127f06a 100644 --- a/src/webflow/types/publish_status.py +++ b/src/webflow/types/publish_status.py @@ -1,21 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class PublishStatus(str, enum.Enum): - """ - Indicate whether your Product should be set as "staging" or "live" - """ - - STAGING = "staging" - LIVE = "live" - - def visit(self, staging: typing.Callable[[], T_Result], live: typing.Callable[[], T_Result]) -> T_Result: - if self is PublishStatus.STAGING: - return staging() - if self is PublishStatus.LIVE: - return live() +PublishStatus = typing.Union[typing.Literal["staging", "live"], typing.Any] diff --git a/src/webflow/types/redirect.py b/src/webflow/types/redirect.py new file mode 100644 index 0000000..0205f34 --- /dev/null +++ b/src/webflow/types/redirect.py @@ -0,0 +1,42 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Redirect(UniversalBaseModel): + """ + A single redirection rule, specifying a source URL and a destination URL. + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + The ID of the specific redirect rule + """ + + from_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="fromUrl")] = pydantic.Field( + default=None + ) + """ + The source URL path that will be redirected. + """ + + to_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="toUrl")] = pydantic.Field( + default=None + ) + """ + The target URL path where the user or client will be redirected. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/redirects.py b/src/webflow/types/redirects.py new file mode 100644 index 0000000..bd466b2 --- /dev/null +++ b/src/webflow/types/redirects.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .redirect import Redirect +import pydantic +from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Redirects(UniversalBaseModel): + """ + Site redirects response + """ + + redirects: typing.Optional[typing.List[Redirect]] = pydantic.Field(default=None) + """ + List of redirects for a given site + """ + + pagination: typing.Optional[Pagination] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/registered_script_list.py b/src/webflow/types/registered_script_list.py index 6ed8db3..ddfff8d 100644 --- a/src/webflow/types/registered_script_list.py +++ b/src/webflow/types/registered_script_list.py @@ -1,38 +1,28 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .custom_code_hosted_response import CustomCodeHostedResponse +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class RegisteredScriptList(pydantic_v1.BaseModel): +class RegisteredScriptList(UniversalBaseModel): """ A list of scripts registered to the site """ - registered_scripts: typing.Optional[typing.List[CustomCodeHostedResponse]] = pydantic_v1.Field( - alias="registeredScripts", default=None - ) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + registered_scripts: typing_extensions.Annotated[ + typing.Optional[typing.List[CustomCodeHostedResponse]], FieldMetadata(alias="registeredScripts") + ] = None - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/script_apply.py b/src/webflow/types/script_apply.py index 38405ee..6ba1930 100644 --- a/src/webflow/types/script_apply.py +++ b/src/webflow/types/script_apply.py @@ -1,48 +1,38 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt -import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic from .script_apply_location import ScriptApplyLocation +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class ScriptApply(pydantic_v1.BaseModel): - id: str = pydantic_v1.Field() +class ScriptApply(UniversalBaseModel): + id: str = pydantic.Field() """ ID of the registered custom code script """ - location: ScriptApplyLocation = pydantic_v1.Field() + location: ScriptApplyLocation = pydantic.Field() """ Location of the script, either in the header or footer of the published site """ - version: str = pydantic_v1.Field() + version: str = pydantic.Field() """ - Semantic Version String for the registered script _e.g. 0.0.1_ + Semantic Version String for the registered script *e.g. 0.0.1* """ - attributes: typing.Optional[typing.Dict[str, typing.Any]] = pydantic_v1.Field(default=None) + attributes: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) """ Developer-specified key/value pairs to be applied as attributes to the script """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/script_apply_list.py b/src/webflow/types/script_apply_list.py index 46b1a69..e89b54d 100644 --- a/src/webflow/types/script_apply_list.py +++ b/src/webflow/types/script_apply_list.py @@ -1,45 +1,39 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .script_apply import ScriptApply +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class ScriptApplyList(pydantic_v1.BaseModel): - scripts: typing.Optional[typing.List[ScriptApply]] = pydantic_v1.Field(default=None) +class ScriptApplyList(UniversalBaseModel): + scripts: typing.Optional[typing.List[ScriptApply]] = pydantic.Field(default=None) """ A list of scripts applied to a Site or a Page """ - last_updated: typing.Optional[str] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ Date when the Site's scripts were last updated """ - created_on: typing.Optional[str] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) """ Date when the Site's scripts were created """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/script_apply_location.py b/src/webflow/types/script_apply_location.py index e5435c8..6ee3b0a 100644 --- a/src/webflow/types/script_apply_location.py +++ b/src/webflow/types/script_apply_location.py @@ -1,21 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class ScriptApplyLocation(str, enum.Enum): - """ - Location of the script, either in the header or footer of the published site - """ - - HEADER = "header" - FOOTER = "footer" - - def visit(self, header: typing.Callable[[], T_Result], footer: typing.Callable[[], T_Result]) -> T_Result: - if self is ScriptApplyLocation.HEADER: - return header() - if self is ScriptApplyLocation.FOOTER: - return footer() +ScriptApplyLocation = typing.Union[typing.Literal["header", "footer"], typing.Any] diff --git a/src/webflow/types/scripts.py b/src/webflow/types/scripts.py index 6ff9844..1f0c1c1 100644 --- a/src/webflow/types/scripts.py +++ b/src/webflow/types/scripts.py @@ -1,7 +1,6 @@ # This file was auto-generated by Fern from our API Definition. import typing - from .script_apply import ScriptApply Scripts = typing.List[ScriptApply] diff --git a/src/webflow/types/site.py b/src/webflow/types/site.py index f00321f..96f66a1 100644 --- a/src/webflow/types/site.py +++ b/src/webflow/types/site.py @@ -1,84 +1,109 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from ..core.serialization import FieldMetadata +import datetime as dt from .domain import Domain from .locales import Locales +from .site_data_collection_type import SiteDataCollectionType +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Site(pydantic_v1.BaseModel): - id: str = pydantic_v1.Field() +class Site(UniversalBaseModel): + id: str = pydantic.Field() """ Unique identifier for the Site """ - workspace_id: typing.Optional[str] = pydantic_v1.Field(alias="workspaceId", default=None) + workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( + pydantic.Field(default=None) + ) """ Unique identifier for the Workspace """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ Date the Site was created """ - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) """ Name given to Site """ - short_name: typing.Optional[str] = pydantic_v1.Field(alias="shortName", default=None) + short_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="shortName")] = pydantic.Field( + default=None + ) """ Slugified version of name """ - last_published: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastPublished", default=None) + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + pydantic.Field(default=None) + ) """ Date the Site was last published """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ Date the Site was last updated """ - preview_url: typing.Optional[str] = pydantic_v1.Field(alias="previewUrl", default=None) + preview_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previewUrl")] = pydantic.Field( + default=None + ) """ URL of a generated image for the given Site """ - time_zone: typing.Optional[str] = pydantic_v1.Field(alias="timeZone", default=None) + time_zone: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="timeZone")] = pydantic.Field( + default=None + ) """ Site timezone set under Site Settings """ - parent_folder_id: typing.Optional[str] = pydantic_v1.Field(alias="parentFolderId", default=None) + parent_folder_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="parentFolderId")] = ( + pydantic.Field(default=None) + ) """ The ID of the parent folder the Site exists in """ - custom_domains: typing.Optional[typing.List[Domain]] = pydantic_v1.Field(alias="customDomains", default=None) + custom_domains: typing_extensions.Annotated[ + typing.Optional[typing.List[Domain]], FieldMetadata(alias="customDomains") + ] = None locales: typing.Optional[Locales] = None + data_collection_enabled: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="dataCollectionEnabled") + ] = pydantic.Field(default=None) + """ + Indicates if data collection is enabled for the site. + """ + + data_collection_type: typing_extensions.Annotated[ + typing.Optional[SiteDataCollectionType], FieldMetadata(alias="dataCollectionType") + ] = pydantic.Field(default=None) + """ + The type of data collection enabled for the site. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_activity_log_item.py b/src/webflow/types/site_activity_log_item.py index a23608c..0ad70ea 100644 --- a/src/webflow/types/site_activity_log_item.py +++ b/src/webflow/types/site_activity_log_item.py @@ -1,45 +1,37 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import typing_extensions +import datetime as dt +from ..core.serialization import FieldMetadata +from .site_activity_log_item_event import SiteActivityLogItemEvent from .site_activity_log_item_resource_operation import SiteActivityLogItemResourceOperation from .site_activity_log_item_user import SiteActivityLogItemUser +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class SiteActivityLogItem(pydantic_v1.BaseModel): +class SiteActivityLogItem(UniversalBaseModel): id: typing.Optional[str] = None - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) - event: typing.Optional[str] = None - resource_operation: typing.Optional[SiteActivityLogItemResourceOperation] = pydantic_v1.Field( - alias="resourceOperation", default=None - ) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + event: typing.Optional[SiteActivityLogItemEvent] = None + resource_operation: typing_extensions.Annotated[ + typing.Optional[SiteActivityLogItemResourceOperation], FieldMetadata(alias="resourceOperation") + ] = None user: typing.Optional[SiteActivityLogItemUser] = None - resource_id: typing.Optional[str] = pydantic_v1.Field(alias="resourceId", default=None) - resource_name: typing.Optional[str] = pydantic_v1.Field(alias="resourceName", default=None) - new_value: typing.Optional[str] = pydantic_v1.Field(alias="newValue", default=None) - previous_value: typing.Optional[str] = pydantic_v1.Field(alias="previousValue", default=None) - payload: typing.Optional[typing.Dict[str, typing.Any]] = None - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) - - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + resource_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="resourceId")] = None + resource_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="resourceName")] = None + new_value: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="newValue")] = None + previous_value: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousValue")] = None + payload: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_activity_log_item_event.py b/src/webflow/types/site_activity_log_item_event.py new file mode 100644 index 0000000..de7a114 --- /dev/null +++ b/src/webflow/types/site_activity_log_item_event.py @@ -0,0 +1,51 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +SiteActivityLogItemEvent = typing.Union[ + typing.Literal[ + "styles_modified", + "site_published", + "ix2_modified_on_page", + "page_dom_modified", + "cms_item", + "backup_created", + "page_custom_code_modified", + "symbols_modified", + "variable_modified", + "variables_modified", + "cms_collection", + "page_settings_modified", + "page_settings_custom_code_modified", + "ix2_modified_on_component", + "ix2_modified_on_class", + "site_custom_code_modified", + "page_duplicated", + "secondary_locale_page_content_modified", + "page_renamed", + "page_created", + "page_deleted", + "site_unpublished", + "backup_restored", + "locale_added", + "branch_created", + "locale_display_name_updated", + "locale_subdirectory_updated", + "branch_merged", + "locale_tag_updated", + "branch_deleted", + "locale_enabled", + "locale_removed", + "locale_disabled", + "library_shared", + "library_unshared", + "library_installed", + "library_uninstalled", + "library_update_shared", + "library_update_accepted", + "branch_review_created", + "branch_review_approved", + "branch_review_canceled", + ], + typing.Any, +] diff --git a/src/webflow/types/site_activity_log_item_resource_operation.py b/src/webflow/types/site_activity_log_item_resource_operation.py index fef8208..59074a7 100644 --- a/src/webflow/types/site_activity_log_item_resource_operation.py +++ b/src/webflow/types/site_activity_log_item_resource_operation.py @@ -1,33 +1,18 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class SiteActivityLogItemResourceOperation(str, enum.Enum): - CREATED = "CREATED" - MODIFIED = "MODIFIED" - PUBLISHED = "PUBLISHED" - UNPUBLISHED = "UNPUBLISHED" - DELETED = "DELETED" - - def visit( - self, - created: typing.Callable[[], T_Result], - modified: typing.Callable[[], T_Result], - published: typing.Callable[[], T_Result], - unpublished: typing.Callable[[], T_Result], - deleted: typing.Callable[[], T_Result], - ) -> T_Result: - if self is SiteActivityLogItemResourceOperation.CREATED: - return created() - if self is SiteActivityLogItemResourceOperation.MODIFIED: - return modified() - if self is SiteActivityLogItemResourceOperation.PUBLISHED: - return published() - if self is SiteActivityLogItemResourceOperation.UNPUBLISHED: - return unpublished() - if self is SiteActivityLogItemResourceOperation.DELETED: - return deleted() +SiteActivityLogItemResourceOperation = typing.Union[ + typing.Literal[ + "CREATED", + "MODIFIED", + "PUBLISHED", + "UNPUBLISHED", + "DELETED", + "GROUP_REORDERED", + "GROUP_CREATED", + "GROUP_DELETED", + "REORDERED", + ], + typing.Any, +] diff --git a/src/webflow/types/site_activity_log_item_user.py b/src/webflow/types/site_activity_log_item_user.py index 60e7846..b372c65 100644 --- a/src/webflow/types/site_activity_log_item_user.py +++ b/src/webflow/types/site_activity_log_item_user.py @@ -1,32 +1,22 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class SiteActivityLogItemUser(pydantic_v1.BaseModel): +class SiteActivityLogItemUser(UniversalBaseModel): id: typing.Optional[str] = None - display_name: typing.Optional[str] = pydantic_v1.Field(alias="displayName", default=None) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = None - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_activity_log_response.py b/src/webflow/types/site_activity_log_response.py index 69bcc31..32606a7 100644 --- a/src/webflow/types/site_activity_log_response.py +++ b/src/webflow/types/site_activity_log_response.py @@ -1,32 +1,22 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 -from .pagination import Pagination from .site_activity_log_item import SiteActivityLogItem +from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class SiteActivityLogResponse(pydantic_v1.BaseModel): +class SiteActivityLogResponse(UniversalBaseModel): items: typing.Optional[typing.List[SiteActivityLogItem]] = None pagination: typing.Optional[Pagination] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_data_collection_type.py b/src/webflow/types/site_data_collection_type.py new file mode 100644 index 0000000..88d6188 --- /dev/null +++ b/src/webflow/types/site_data_collection_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +SiteDataCollectionType = typing.Union[typing.Literal["always", "optOut", "disabled"], typing.Any] diff --git a/src/webflow/types/site_plan.py b/src/webflow/types/site_plan.py new file mode 100644 index 0000000..a8feecc --- /dev/null +++ b/src/webflow/types/site_plan.py @@ -0,0 +1,38 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .site_plan_id import SitePlanId +import pydantic +from .site_plan_name import SitePlanName +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SitePlan(UniversalBaseModel): + id: typing.Optional[SitePlanId] = pydantic.Field(default=None) + """ + ID of the hosting plan. + """ + + name: typing.Optional[SitePlanName] = pydantic.Field(default=None) + """ + Name of the hosting plan. + """ + + pricing_info: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pricingInfo")] = ( + pydantic.Field(default=None) + ) + """ + URL for more information about Webflow hosting plan pricing. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_plan_id.py b/src/webflow/types/site_plan_id.py new file mode 100644 index 0000000..2d0d676 --- /dev/null +++ b/src/webflow/types/site_plan_id.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +SitePlanId = typing.Union[ + typing.Literal[ + "hosting-basic-v3", + "hosting-cms-v3", + "hosting-business-v3", + "hosting-ecommerce-standard-v2", + "hosting-ecommerce-plus-v2", + "hosting-ecommerce-advanced-v2", + "hosting-basic-v4", + "hosting-cms-v4", + "hosting-business-v4", + "hosting-ecommerce-standard-v3", + "hosting-ecommerce-plus-v3", + "hosting-ecommerce-advanced-v3", + ], + typing.Any, +] diff --git a/src/webflow/types/site_plan_name.py b/src/webflow/types/site_plan_name.py new file mode 100644 index 0000000..f892f6c --- /dev/null +++ b/src/webflow/types/site_plan_name.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +SitePlanName = typing.Union[ + typing.Literal[ + "Basic Hosting", + "CMS Hosting", + "Business Hosting", + "ECommerce Standard Hosting", + "ECommerce Plus Hosting", + "ECommerce Advanced Hosting", + ], + typing.Any, +] diff --git a/src/webflow/types/sites.py b/src/webflow/types/sites.py index 18a9338..d293ce2 100644 --- a/src/webflow/types/sites.py +++ b/src/webflow/types/sites.py @@ -1,30 +1,20 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .site import Site +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class Sites(pydantic_v1.BaseModel): +class Sites(UniversalBaseModel): sites: typing.Optional[typing.List[Site]] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/sku.py b/src/webflow/types/sku.py index ae2008e..79f159a 100644 --- a/src/webflow/types/sku.py +++ b/src/webflow/types/sku.py @@ -1,61 +1,60 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt from .sku_field_data import SkuFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Sku(pydantic_v1.BaseModel): +class Sku(UniversalBaseModel): """ The SKU object """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for the Product """ - cms_locale_id: typing.Optional[str] = pydantic_v1.Field(alias="cmsLocaleId", default=None) + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) """ Identifier for the locale of the CMS item """ - last_published: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastPublished", default=None) + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + pydantic.Field(default=None) + ) """ The date the Product was last published """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ The date the Product was last updated """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ The date the Product was created """ - field_data: typing.Optional[SkuFieldData] = pydantic_v1.Field(alias="fieldData", default=None) - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + field_data: typing_extensions.Annotated[typing.Optional[SkuFieldData], FieldMetadata(alias="fieldData")] = None - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/sku_field_data.py b/src/webflow/types/sku_field_data.py index d90c09d..e20efdb 100644 --- a/src/webflow/types/sku_field_data.py +++ b/src/webflow/types/sku_field_data.py @@ -1,77 +1,69 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from .sku_value_list import SkuValueList +from ..core.serialization import FieldMetadata +import pydantic +from .sku_field_data_price import SkuFieldDataPrice from .sku_field_data_compare_at_price import SkuFieldDataCompareAtPrice from .sku_field_data_ec_sku_billing_method import SkuFieldDataEcSkuBillingMethod from .sku_field_data_ec_sku_subscription_plan import SkuFieldDataEcSkuSubscriptionPlan -from .sku_field_data_price import SkuFieldDataPrice -from .sku_value_list import SkuValueList +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class SkuFieldData(pydantic_v1.BaseModel): +class SkuFieldData(UniversalBaseModel): """ Standard and Custom fields for a SKU """ - sku_values: typing.Optional[SkuValueList] = pydantic_v1.Field(alias="sku-values", default=None) - name: str = pydantic_v1.Field() + sku_values: typing_extensions.Annotated[typing.Optional[SkuValueList], FieldMetadata(alias="sku-values")] = None + name: str = pydantic.Field() """ Name of the Product """ - slug: str = pydantic_v1.Field() + slug: str = pydantic.Field() """ URL structure of the Product in your site. """ - price: SkuFieldDataPrice = pydantic_v1.Field() + price: SkuFieldDataPrice = pydantic.Field() """ price of SKU """ - compare_at_price: typing.Optional[SkuFieldDataCompareAtPrice] = pydantic_v1.Field( - alias="compare-at-price", default=None - ) + compare_at_price: typing_extensions.Annotated[ + typing.Optional[SkuFieldDataCompareAtPrice], FieldMetadata(alias="compare-at-price") + ] = pydantic.Field(default=None) """ comparison price of SKU """ - ec_sku_billing_method: typing.Optional[SkuFieldDataEcSkuBillingMethod] = pydantic_v1.Field( - alias="ec-sku-billing-method", default=None - ) - ec_sku_subscription_plan: typing.Optional[SkuFieldDataEcSkuSubscriptionPlan] = pydantic_v1.Field( - alias="ec-sku-subscription-plan", default=None + ec_sku_billing_method: typing_extensions.Annotated[ + typing.Optional[SkuFieldDataEcSkuBillingMethod], FieldMetadata(alias="ec-sku-billing-method") + ] = None + ec_sku_subscription_plan: typing_extensions.Annotated[ + typing.Optional[SkuFieldDataEcSkuSubscriptionPlan], FieldMetadata(alias="ec-sku-subscription-plan") + ] = None + track_inventory: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="track-inventory")] = ( + pydantic.Field(default=None) ) - track_inventory: typing.Optional[bool] = pydantic_v1.Field(alias="track-inventory", default=None) """ A boolean indicating whether inventory for this product should be tracked. """ - quantity: typing.Optional[float] = pydantic_v1.Field(default=None) + quantity: typing.Optional[float] = pydantic.Field(default=None) """ Quantity of SKU that will be tracked as items are ordered. """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/sku_field_data_compare_at_price.py b/src/webflow/types/sku_field_data_compare_at_price.py index 2a72eb0..6b2347f 100644 --- a/src/webflow/types/sku_field_data_compare_at_price.py +++ b/src/webflow/types/sku_field_data_compare_at_price.py @@ -1,41 +1,31 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class SkuFieldDataCompareAtPrice(pydantic_v1.BaseModel): +class SkuFieldDataCompareAtPrice(UniversalBaseModel): """ comparison price of SKU """ - value: typing.Optional[float] = pydantic_v1.Field(default=None) + value: typing.Optional[float] = pydantic.Field(default=None) """ Price of SKU """ - unit: typing.Optional[str] = pydantic_v1.Field(default=None) + unit: typing.Optional[str] = pydantic.Field(default=None) """ Currency of Item """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/sku_field_data_ec_sku_billing_method.py b/src/webflow/types/sku_field_data_ec_sku_billing_method.py index 044f305..e0cbcb4 100644 --- a/src/webflow/types/sku_field_data_ec_sku_billing_method.py +++ b/src/webflow/types/sku_field_data_ec_sku_billing_method.py @@ -1,17 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class SkuFieldDataEcSkuBillingMethod(str, enum.Enum): - ONE_TIME = "one-time" - SUBSCRIPTION = "subscription" - - def visit(self, one_time: typing.Callable[[], T_Result], subscription: typing.Callable[[], T_Result]) -> T_Result: - if self is SkuFieldDataEcSkuBillingMethod.ONE_TIME: - return one_time() - if self is SkuFieldDataEcSkuBillingMethod.SUBSCRIPTION: - return subscription() +SkuFieldDataEcSkuBillingMethod = typing.Union[typing.Literal["one-time", "subscription"], typing.Any] diff --git a/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py b/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py index cc9e529..24c85a7 100644 --- a/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py +++ b/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py @@ -1,46 +1,36 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .sku_field_data_ec_sku_subscription_plan_interval import SkuFieldDataEcSkuSubscriptionPlanInterval +import pydantic from .sku_field_data_ec_sku_subscription_plan_plans_item import SkuFieldDataEcSkuSubscriptionPlanPlansItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class SkuFieldDataEcSkuSubscriptionPlan(pydantic_v1.BaseModel): - interval: typing.Optional[SkuFieldDataEcSkuSubscriptionPlanInterval] = pydantic_v1.Field(default=None) +class SkuFieldDataEcSkuSubscriptionPlan(UniversalBaseModel): + interval: typing.Optional[SkuFieldDataEcSkuSubscriptionPlanInterval] = pydantic.Field(default=None) """ Interval of subscription renewal """ - frequency: typing.Optional[float] = pydantic_v1.Field(default=None) + frequency: typing.Optional[float] = pydantic.Field(default=None) """ Frequncy of billing within interval """ - trial: typing.Optional[float] = pydantic_v1.Field(default=None) + trial: typing.Optional[float] = pydantic.Field(default=None) """ Number of days of a trial """ plans: typing.Optional[typing.List[SkuFieldDataEcSkuSubscriptionPlanPlansItem]] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/sku_field_data_ec_sku_subscription_plan_interval.py b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_interval.py index ffa978f..08d8923 100644 --- a/src/webflow/types/sku_field_data_ec_sku_subscription_plan_interval.py +++ b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_interval.py @@ -1,33 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class SkuFieldDataEcSkuSubscriptionPlanInterval(str, enum.Enum): - """ - Interval of subscription renewal - """ - - DAY = "day" - WEEK = "week" - MONTH = "month" - YEAR = "year" - - def visit( - self, - day: typing.Callable[[], T_Result], - week: typing.Callable[[], T_Result], - month: typing.Callable[[], T_Result], - year: typing.Callable[[], T_Result], - ) -> T_Result: - if self is SkuFieldDataEcSkuSubscriptionPlanInterval.DAY: - return day() - if self is SkuFieldDataEcSkuSubscriptionPlanInterval.WEEK: - return week() - if self is SkuFieldDataEcSkuSubscriptionPlanInterval.MONTH: - return month() - if self is SkuFieldDataEcSkuSubscriptionPlanInterval.YEAR: - return year() +SkuFieldDataEcSkuSubscriptionPlanInterval = typing.Union[typing.Literal["day", "week", "month", "year"], typing.Any] diff --git a/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py index 074cc7a..714642e 100644 --- a/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py +++ b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py @@ -1,43 +1,33 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic from .sku_field_data_ec_sku_subscription_plan_plans_item_status import SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class SkuFieldDataEcSkuSubscriptionPlanPlansItem(pydantic_v1.BaseModel): - platform: typing.Optional[typing.Literal["stripe"]] = pydantic_v1.Field(default=None) +class SkuFieldDataEcSkuSubscriptionPlanPlansItem(UniversalBaseModel): + platform: typing.Optional[typing.Literal["stripe"]] = pydantic.Field(default=None) """ The platform of the subscription plan """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: typing.Optional[str] = pydantic.Field(default=None) """ The unique identifier of the plan """ - status: typing.Optional[SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus] = pydantic_v1.Field(default=None) + status: typing.Optional[SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus] = pydantic.Field(default=None) """ The status of the plan """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item_status.py b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item_status.py index d5daba6..549e5aa 100644 --- a/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item_status.py +++ b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item_status.py @@ -1,29 +1,7 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus(str, enum.Enum): - """ - The status of the plan - """ - - ACTIVE = "active" - INACTIVE = "inactive" - CANCELED = "canceled" - - def visit( - self, - active: typing.Callable[[], T_Result], - inactive: typing.Callable[[], T_Result], - canceled: typing.Callable[[], T_Result], - ) -> T_Result: - if self is SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus.ACTIVE: - return active() - if self is SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus.INACTIVE: - return inactive() - if self is SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus.CANCELED: - return canceled() +SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus = typing.Union[ + typing.Literal["active", "inactive", "canceled"], typing.Any +] diff --git a/src/webflow/types/sku_field_data_price.py b/src/webflow/types/sku_field_data_price.py index e72419b..45ff611 100644 --- a/src/webflow/types/sku_field_data_price.py +++ b/src/webflow/types/sku_field_data_price.py @@ -1,41 +1,31 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class SkuFieldDataPrice(pydantic_v1.BaseModel): +class SkuFieldDataPrice(UniversalBaseModel): """ price of SKU """ - value: typing.Optional[float] = pydantic_v1.Field(default=None) + value: typing.Optional[float] = pydantic.Field(default=None) """ Price of SKU """ - unit: typing.Optional[str] = pydantic_v1.Field(default=None) + unit: typing.Optional[str] = pydantic.Field(default=None) """ Currency of Item """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/sku_property_list.py b/src/webflow/types/sku_property_list.py index 85093e9..f4e0862 100644 --- a/src/webflow/types/sku_property_list.py +++ b/src/webflow/types/sku_property_list.py @@ -1,47 +1,37 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .sku_property_list_enum_item import SkuPropertyListEnumItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class SkuPropertyList(pydantic_v1.BaseModel): +class SkuPropertyList(UniversalBaseModel): """ A variant/option type for a SKU """ - id: str = pydantic_v1.Field() + id: str = pydantic.Field() """ Unique identifier for a collection of Product Variants """ - name: str = pydantic_v1.Field() + name: str = pydantic.Field() """ Name of the collection of Product Variants """ - enum: typing.List[SkuPropertyListEnumItem] = pydantic_v1.Field() + enum: typing.List[SkuPropertyListEnumItem] = pydantic.Field() """ The individual Product variants that are contained within the collection """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/sku_property_list_enum_item.py b/src/webflow/types/sku_property_list_enum_item.py index 6a26009..f35e6d0 100644 --- a/src/webflow/types/sku_property_list_enum_item.py +++ b/src/webflow/types/sku_property_list_enum_item.py @@ -1,46 +1,36 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class SkuPropertyListEnumItem(pydantic_v1.BaseModel): +class SkuPropertyListEnumItem(UniversalBaseModel): """ Enumerated Product variants/Options for the SKU """ - id: str = pydantic_v1.Field() + id: str = pydantic.Field() """ Unique identifier for a Product variant/Option """ - name: str = pydantic_v1.Field() + name: str = pydantic.Field() """ Name of the Product variant/Option """ - slug: str = pydantic_v1.Field() + slug: str = pydantic.Field() """ Slug for the Product variant/Option in the Site URL structure """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/stripe_card.py b/src/webflow/types/stripe_card.py index a6ba3f2..ccc45ae 100644 --- a/src/webflow/types/stripe_card.py +++ b/src/webflow/types/stripe_card.py @@ -1,55 +1,49 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +from ..core.serialization import FieldMetadata +import pydantic from .stripe_card_brand import StripeCardBrand from .stripe_card_expires import StripeCardExpires +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class StripeCard(pydantic_v1.BaseModel): +class StripeCard(UniversalBaseModel): """ Details on the card used to fulfill this order, if this order was finalized with Stripe. """ - last_4: typing.Optional[str] = pydantic_v1.Field(alias="last4", default=None) + last_4: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="last4")] = pydantic.Field( + default=None + ) """ The last 4 digits on the card as a string """ - brand: typing.Optional[StripeCardBrand] = pydantic_v1.Field(default=None) + brand: typing.Optional[StripeCardBrand] = pydantic.Field(default=None) """ The card's brand (ie. credit card network) """ - owner_name: typing.Optional[str] = pydantic_v1.Field(alias="ownerName", default=None) + owner_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="ownerName")] = pydantic.Field( + default=None + ) """ The name on the card. """ - expires: typing.Optional[StripeCardExpires] = pydantic_v1.Field(default=None) + expires: typing.Optional[StripeCardExpires] = pydantic.Field(default=None) """ The card's expiration date. """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/stripe_card_brand.py b/src/webflow/types/stripe_card_brand.py index 121ce40..3edc472 100644 --- a/src/webflow/types/stripe_card_brand.py +++ b/src/webflow/types/stripe_card_brand.py @@ -1,45 +1,7 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class StripeCardBrand(str, enum.Enum): - """ - The card's brand (ie. credit card network) - """ - - VISA = "Visa" - AMERICAN_EXPRESS = "American Express" - MASTER_CARD = "MasterCard" - DISCOVER = "Discover" - JCB = "JCB" - DINERS_CLUB = "Diners Club" - UNKNOWN = "Unknown" - - def visit( - self, - visa: typing.Callable[[], T_Result], - american_express: typing.Callable[[], T_Result], - master_card: typing.Callable[[], T_Result], - discover: typing.Callable[[], T_Result], - jcb: typing.Callable[[], T_Result], - diners_club: typing.Callable[[], T_Result], - unknown: typing.Callable[[], T_Result], - ) -> T_Result: - if self is StripeCardBrand.VISA: - return visa() - if self is StripeCardBrand.AMERICAN_EXPRESS: - return american_express() - if self is StripeCardBrand.MASTER_CARD: - return master_card() - if self is StripeCardBrand.DISCOVER: - return discover() - if self is StripeCardBrand.JCB: - return jcb() - if self is StripeCardBrand.DINERS_CLUB: - return diners_club() - if self is StripeCardBrand.UNKNOWN: - return unknown() +StripeCardBrand = typing.Union[ + typing.Literal["Visa", "American Express", "MasterCard", "Discover", "JCB", "Diners Club", "Unknown"], typing.Any +] diff --git a/src/webflow/types/stripe_card_expires.py b/src/webflow/types/stripe_card_expires.py index b3eb064..3ce14d9 100644 --- a/src/webflow/types/stripe_card_expires.py +++ b/src/webflow/types/stripe_card_expires.py @@ -1,41 +1,31 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class StripeCardExpires(pydantic_v1.BaseModel): +class StripeCardExpires(UniversalBaseModel): """ The card's expiration date. """ - year: typing.Optional[float] = pydantic_v1.Field(default=None) + year: typing.Optional[float] = pydantic.Field(default=None) """ Year that the card expires """ - month: typing.Optional[float] = pydantic_v1.Field(default=None) + month: typing.Optional[float] = pydantic.Field(default=None) """ Month that the card expires """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/stripe_details.py b/src/webflow/types/stripe_details.py index 3c03e22..9bd170a 100644 --- a/src/webflow/types/stripe_details.py +++ b/src/webflow/types/stripe_details.py @@ -1,73 +1,79 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions import typing +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class StripeDetails(pydantic_v1.BaseModel): +class StripeDetails(UniversalBaseModel): """ An object with various Stripe IDs, useful for linking into the stripe dashboard. """ - subscription_id: typing.Optional[str] = pydantic_v1.Field(alias="subscriptionId", default=None) + subscription_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="subscriptionId")] = ( + pydantic.Field(default=None) + ) """ Stripe-generated identifier for the Subscription """ - payment_method: typing.Optional[str] = pydantic_v1.Field(alias="paymentMethod", default=None) + payment_method: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="paymentMethod")] = ( + pydantic.Field(default=None) + ) """ Stripe-generated identifier for the PaymentMethod used """ - payment_intent_id: typing.Optional[str] = pydantic_v1.Field(alias="paymentIntentId", default=None) + payment_intent_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="paymentIntentId")] = ( + pydantic.Field(default=None) + ) """ Stripe-generated identifier for the PaymentIntent, or null """ - customer_id: typing.Optional[str] = pydantic_v1.Field(alias="customerId", default=None) + customer_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="customerId")] = pydantic.Field( + default=None + ) """ Stripe-generated customer identifier, or null """ - charge_id: typing.Optional[str] = pydantic_v1.Field(alias="chargeId", default=None) + charge_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="chargeId")] = pydantic.Field( + default=None + ) """ Stripe-generated charge identifier, or null """ - dispute_id: typing.Optional[str] = pydantic_v1.Field(alias="disputeId", default=None) + dispute_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="disputeId")] = pydantic.Field( + default=None + ) """ Stripe-generated dispute identifier, or null """ - refund_id: typing.Optional[str] = pydantic_v1.Field(alias="refundId", default=None) + refund_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="refundId")] = pydantic.Field( + default=None + ) """ Stripe-generated refund identifier, or null """ - refund_reason: typing.Optional[str] = pydantic_v1.Field(alias="refundReason", default=None) + refund_reason: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="refundReason")] = ( + pydantic.Field(default=None) + ) """ Stripe-generated refund reason, or null """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/text.py b/src/webflow/types/text.py new file mode 100644 index 0000000..18f8501 --- /dev/null +++ b/src/webflow/types/text.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Text(UniversalBaseModel): + html: typing.Optional[str] = pydantic.Field(default=None) + """ + The HTML content of the text node. + """ + + text: typing.Optional[str] = pydantic.Field(default=None) + """ + The raw text content of the text node. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/text_node.py b/src/webflow/types/text_node.py index a6a7a6d..1e16717 100644 --- a/src/webflow/types/text_node.py +++ b/src/webflow/types/text_node.py @@ -1,34 +1,33 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +from .text_node_text import TextNodeText +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class TextNode(pydantic_v1.BaseModel): +class TextNode(UniversalBaseModel): """ - Represents textual content within the DOM. It contains both the raw text and its HTML representation, allowing for flexibility in rendering and processing. Additional attributes can be associated with the text for styling or other purposes. + Represents text content within the DOM. It contains both the raw text and its HTML representation. Additional attributes can be associated with the text for styling or other purposes. """ - html: typing.Optional[str] = None - text: typing.Optional[str] = None - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Node UUID + """ - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} + text: typing.Optional[TextNodeText] = None + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + The custom attributes of the node + """ - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/text_node_text.py b/src/webflow/types/text_node_text.py new file mode 100644 index 0000000..895dc0b --- /dev/null +++ b/src/webflow/types/text_node_text.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class TextNodeText(UniversalBaseModel): + html: typing.Optional[str] = pydantic.Field(default=None) + """ + The HTML content of the text node. + """ + + text: typing.Optional[str] = pydantic.Field(default=None) + """ + The raw text content of the text node. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/text_node_write.py b/src/webflow/types/text_node_write.py new file mode 100644 index 0000000..a16c800 --- /dev/null +++ b/src/webflow/types/text_node_write.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class TextNodeWrite(UniversalBaseModel): + """ + Update a text node + """ + + node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() + """ + Node UUID + """ + + text: str = pydantic.Field() + """ + HTML content of the node, including the HTML tag. The HTML tags must be the same as what's returned from the Get Content endpoint. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/trigger_type.py b/src/webflow/types/trigger_type.py index c8ff70f..e12b650 100644 --- a/src/webflow/types/trigger_type.py +++ b/src/webflow/types/trigger_type.py @@ -1,91 +1,24 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class TriggerType(str, enum.Enum): - """ - - `form_submission` - Sends the [form_submission](#form_submission) event - - `site_publish` - Sends a [site_publish](#site_publish) event - - `page_created` - Send the [page_created](#page_created) event - - `page_metadata_updated` - Sends the [page_metadata_updated](#page_metadata_updated) event - - `page_deleted` - Sends the [page_deleted](#page_deleted) event - - `ecomm_new_order` - Sends the new [ecomm_new_order](#ecomm_new_order) event - - `ecomm_order_changed` - Sends the [ecomm_order_changed](#ecomm_order_changed) event - - `ecomm_inventory_changed` - Sends the [ecomm_inventory_changed](#ecomm_inventory_changed) event - - `user_account_added` - Sends the [user_account_added](#user_account_added) event - - `user_account_updated` - Sends the [user_account_updated](#user_account_updated) event - - `user_account_deleted` - Sends the [user_account_deleted](#user_account_deleted) event - - `collection_item_created` - Sends the [collection_item_created](#collection_item_created) event - - `collection_item_changed` - Sends the [collection_item_changed](#collection_item_changed) event - - `collection_item_deleted` - Sends the [collection_item_deleted](#collection_item_deleted) event - - `collection_item_unpublished` - Sends the [collection_item_unpublished](#collection_item_unpublished) event - """ - - FORM_SUBMISSION = "form_submission" - SITE_PUBLISH = "site_publish" - PAGE_CREATED = "page_created" - PAGE_METADATA_UPDATED = "page_metadata_updated" - PAGE_DELETED = "page_deleted" - ECOMM_NEW_ORDER = "ecomm_new_order" - ECOMM_ORDER_CHANGED = "ecomm_order_changed" - ECOMM_INVENTORY_CHANGED = "ecomm_inventory_changed" - USER_ACCOUNT_ADDED = "user_account_added" - USER_ACCOUNT_UPDATED = "user_account_updated" - USER_ACCOUNT_DELETED = "user_account_deleted" - COLLECTION_ITEM_CREATED = "collection_item_created" - COLLECTION_ITEM_CHANGED = "collection_item_changed" - COLLECTION_ITEM_DELETED = "collection_item_deleted" - COLLECTION_ITEM_UNPUBLISHED = "collection_item_unpublished" - - def visit( - self, - form_submission: typing.Callable[[], T_Result], - site_publish: typing.Callable[[], T_Result], - page_created: typing.Callable[[], T_Result], - page_metadata_updated: typing.Callable[[], T_Result], - page_deleted: typing.Callable[[], T_Result], - ecomm_new_order: typing.Callable[[], T_Result], - ecomm_order_changed: typing.Callable[[], T_Result], - ecomm_inventory_changed: typing.Callable[[], T_Result], - user_account_added: typing.Callable[[], T_Result], - user_account_updated: typing.Callable[[], T_Result], - user_account_deleted: typing.Callable[[], T_Result], - collection_item_created: typing.Callable[[], T_Result], - collection_item_changed: typing.Callable[[], T_Result], - collection_item_deleted: typing.Callable[[], T_Result], - collection_item_unpublished: typing.Callable[[], T_Result], - ) -> T_Result: - if self is TriggerType.FORM_SUBMISSION: - return form_submission() - if self is TriggerType.SITE_PUBLISH: - return site_publish() - if self is TriggerType.PAGE_CREATED: - return page_created() - if self is TriggerType.PAGE_METADATA_UPDATED: - return page_metadata_updated() - if self is TriggerType.PAGE_DELETED: - return page_deleted() - if self is TriggerType.ECOMM_NEW_ORDER: - return ecomm_new_order() - if self is TriggerType.ECOMM_ORDER_CHANGED: - return ecomm_order_changed() - if self is TriggerType.ECOMM_INVENTORY_CHANGED: - return ecomm_inventory_changed() - if self is TriggerType.USER_ACCOUNT_ADDED: - return user_account_added() - if self is TriggerType.USER_ACCOUNT_UPDATED: - return user_account_updated() - if self is TriggerType.USER_ACCOUNT_DELETED: - return user_account_deleted() - if self is TriggerType.COLLECTION_ITEM_CREATED: - return collection_item_created() - if self is TriggerType.COLLECTION_ITEM_CHANGED: - return collection_item_changed() - if self is TriggerType.COLLECTION_ITEM_DELETED: - return collection_item_deleted() - if self is TriggerType.COLLECTION_ITEM_UNPUBLISHED: - return collection_item_unpublished() +TriggerType = typing.Union[ + typing.Literal[ + "form_submission", + "site_publish", + "page_created", + "page_metadata_updated", + "page_deleted", + "ecomm_new_order", + "ecomm_order_changed", + "ecomm_inventory_changed", + "user_account_added", + "user_account_updated", + "user_account_deleted", + "collection_item_created", + "collection_item_changed", + "collection_item_deleted", + "collection_item_unpublished", + ], + typing.Any, +] diff --git a/src/webflow/types/user.py b/src/webflow/types/user.py index c443c97..a27a063 100644 --- a/src/webflow/types/user.py +++ b/src/webflow/types/user.py @@ -1,80 +1,81 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt +from .user_status import UserStatus from .user_access_groups_item import UserAccessGroupsItem from .user_data import UserData -from .user_status import UserStatus +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class User(pydantic_v1.BaseModel): +class User(UniversalBaseModel): """ The fields that define the schema for a given Item are based on the Collection that Item belongs to. Beyond the user defined fields, there are a handful of additional fields that are automatically created for all items """ - id: typing.Optional[str] = pydantic_v1.Field(default=None) + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for the User """ - is_email_verified: typing.Optional[bool] = pydantic_v1.Field(alias="isEmailVerified", default=None) + is_email_verified: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEmailVerified")] = ( + pydantic.Field(default=None) + ) """ Shows whether the user has verified their email address """ - last_updated: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastUpdated", default=None) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) """ The timestamp the user was updated """ - invited_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="invitedOn", default=None) + invited_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="invitedOn")] = ( + pydantic.Field(default=None) + ) """ The timestamp the user was invited """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ The timestamp the user was created """ - last_login: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastLogin", default=None) + last_login: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastLogin")] = ( + pydantic.Field(default=None) + ) """ The timestamp the user was logged in """ - status: typing.Optional[UserStatus] = pydantic_v1.Field(default=None) + status: typing.Optional[UserStatus] = pydantic.Field(default=None) """ The status of the user """ - access_groups: typing.Optional[typing.List[UserAccessGroupsItem]] = pydantic_v1.Field( - alias="accessGroups", default=None - ) + access_groups: typing_extensions.Annotated[ + typing.Optional[typing.List[UserAccessGroupsItem]], FieldMetadata(alias="accessGroups") + ] = pydantic.Field(default=None) """ Access groups the user belongs to """ data: typing.Optional[UserData] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_access_groups_item.py b/src/webflow/types/user_access_groups_item.py index 61aa168..55ab6b3 100644 --- a/src/webflow/types/user_access_groups_item.py +++ b/src/webflow/types/user_access_groups_item.py @@ -1,45 +1,34 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic from .user_access_groups_item_type import UserAccessGroupsItemType +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class UserAccessGroupsItem(pydantic_v1.BaseModel): +class UserAccessGroupsItem(UniversalBaseModel): """ Access group slugs and types """ - slug: typing.Optional[str] = pydantic_v1.Field(default=None) + slug: typing.Optional[str] = pydantic.Field(default=None) """ Access group identifier for APIs """ - type: typing.Optional[UserAccessGroupsItemType] = pydantic_v1.Field(default=None) + type: typing.Optional[UserAccessGroupsItemType] = pydantic.Field(default=None) """ The type of access group based on how it was assigned to the user. - - - `admin` - Assigned to the user via API or in the designer - - `ecommerce` - Assigned to the user via an ecommerce purchase + * `admin` - Assigned to the user via API or in the designer + * `ecommerce` - Assigned to the user via an ecommerce purchase """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_access_groups_item_type.py b/src/webflow/types/user_access_groups_item_type.py index f30d5ee..8d9c81c 100644 --- a/src/webflow/types/user_access_groups_item_type.py +++ b/src/webflow/types/user_access_groups_item_type.py @@ -1,24 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class UserAccessGroupsItemType(str, enum.Enum): - """ - The type of access group based on how it was assigned to the user. - - - `admin` - Assigned to the user via API or in the designer - - `ecommerce` - Assigned to the user via an ecommerce purchase - """ - - ADMIN = "admin" - ECOMMERCE = "ecommerce" - - def visit(self, admin: typing.Callable[[], T_Result], ecommerce: typing.Callable[[], T_Result]) -> T_Result: - if self is UserAccessGroupsItemType.ADMIN: - return admin() - if self is UserAccessGroupsItemType.ECOMMERCE: - return ecommerce() +UserAccessGroupsItemType = typing.Union[typing.Literal["admin", "ecommerce"], typing.Any] diff --git a/src/webflow/types/user_data.py b/src/webflow/types/user_data.py index 0813b37..08e35ec 100644 --- a/src/webflow/types/user_data.py +++ b/src/webflow/types/user_data.py @@ -1,34 +1,24 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .user_data_data import UserDataData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class UserData(pydantic_v1.BaseModel): +class UserData(UniversalBaseModel): """ An object containing the User's basic info and custom fields """ data: typing.Optional[UserDataData] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_data_data.py b/src/webflow/types/user_data_data.py index 0366831..7bbf36b 100644 --- a/src/webflow/types/user_data_data.py +++ b/src/webflow/types/user_data_data.py @@ -1,54 +1,50 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 - -class UserDataData(pydantic_v1.BaseModel): - name: typing.Optional[str] = pydantic_v1.Field(default=None) +class UserDataData(UniversalBaseModel): + name: typing.Optional[str] = pydantic.Field(default=None) """ The name of the user """ - email: typing.Optional[str] = pydantic_v1.Field(default=None) + email: typing.Optional[str] = pydantic.Field(default=None) """ The email address of the user """ - accept_privacy: typing.Optional[bool] = pydantic_v1.Field(alias="accept-privacy", default=None) + accept_privacy: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="accept-privacy")] = ( + pydantic.Field(default=None) + ) """ Boolean indicating if the user has accepted the privacy policy """ - accept_communications: typing.Optional[bool] = pydantic_v1.Field(alias="accept-communications", default=None) + accept_communications: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="accept-communications") + ] = pydantic.Field(default=None) """ Boolean indicating if the user has accepted to receive communications """ - additional_properties: typing.Optional[str] = pydantic_v1.Field(alias="additionalProperties", default=None) + additional_properties: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="additionalProperties") + ] = pydantic.Field(default=None) """ Custom user attributes """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_limit_reached.py b/src/webflow/types/user_limit_reached.py index 62b0412..7f149c2 100644 --- a/src/webflow/types/user_limit_reached.py +++ b/src/webflow/types/user_limit_reached.py @@ -1,5 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .error import Error +import typing -UserLimitReached = Error +UserLimitReached = typing.Optional[typing.Any] diff --git a/src/webflow/types/user_list.py b/src/webflow/types/user_list.py index ff1732d..b482d69 100644 --- a/src/webflow/types/user_list.py +++ b/src/webflow/types/user_list.py @@ -1,57 +1,47 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic from .user import User +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class UserList(pydantic_v1.BaseModel): +class UserList(UniversalBaseModel): """ The list users results """ - count: typing.Optional[float] = pydantic_v1.Field(default=None) + count: typing.Optional[float] = pydantic.Field(default=None) """ Number of users returned """ - limit: typing.Optional[float] = pydantic_v1.Field(default=None) + limit: typing.Optional[float] = pydantic.Field(default=None) """ The limit specified in the request """ - offset: typing.Optional[float] = pydantic_v1.Field(default=None) + offset: typing.Optional[float] = pydantic.Field(default=None) """ The offset specified for pagination """ - total: typing.Optional[float] = pydantic_v1.Field(default=None) + total: typing.Optional[float] = pydantic.Field(default=None) """ Total number of users in the collection """ - users: typing.Optional[typing.List[User]] = pydantic_v1.Field(default=None) + users: typing.Optional[typing.List[User]] = pydantic.Field(default=None) """ List of Users for a Site """ - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_status.py b/src/webflow/types/user_status.py index 76af17c..9a0147b 100644 --- a/src/webflow/types/user_status.py +++ b/src/webflow/types/user_status.py @@ -1,29 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -import enum import typing -T_Result = typing.TypeVar("T_Result") - - -class UserStatus(str, enum.Enum): - """ - The status of the user - """ - - INVITED = "invited" - VERIFIED = "verified" - UNVERIFIED = "unverified" - - def visit( - self, - invited: typing.Callable[[], T_Result], - verified: typing.Callable[[], T_Result], - unverified: typing.Callable[[], T_Result], - ) -> T_Result: - if self is UserStatus.INVITED: - return invited() - if self is UserStatus.VERIFIED: - return verified() - if self is UserStatus.UNVERIFIED: - return unverified() +UserStatus = typing.Union[typing.Literal["invited", "verified", "unverified"], typing.Any] diff --git a/src/webflow/types/users_not_enabled.py b/src/webflow/types/users_not_enabled.py index 2d9b8d6..05df7dc 100644 --- a/src/webflow/types/users_not_enabled.py +++ b/src/webflow/types/users_not_enabled.py @@ -1,5 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .error import Error +import typing -UsersNotEnabled = Error +UsersNotEnabled = typing.Optional[typing.Any] diff --git a/src/webflow/types/webhook.py b/src/webflow/types/webhook.py index 9697dfb..226c94f 100644 --- a/src/webflow/types/webhook.py +++ b/src/webflow/types/webhook.py @@ -1,66 +1,66 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 +import pydantic +import typing_extensions from .trigger_type import TriggerType +from ..core.serialization import FieldMetadata +from .webhook_filter import WebhookFilter +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -class Webhook(pydantic_v1.BaseModel): - id: typing.Optional[str] = pydantic_v1.Field(default=None) +class Webhook(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for the Webhook registration """ - workspace_id: typing.Optional[str] = pydantic_v1.Field(alias="workspaceId", default=None) + trigger_type: typing_extensions.Annotated[typing.Optional[TriggerType], FieldMetadata(alias="triggerType")] = None + url: typing.Optional[str] = pydantic.Field(default=None) + """ + URL to send the Webhook payload to + """ + + workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( + pydantic.Field(default=None) + ) """ Unique identifier for the Workspace the Webhook is registered in """ - site_id: typing.Optional[str] = pydantic_v1.Field(alias="siteId", default=None) + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) """ Unique identifier for the Site the Webhook is registered in """ - trigger_type: typing.Optional[TriggerType] = pydantic_v1.Field(alias="triggerType", default=None) - filter: typing.Optional[typing.Dict[str, typing.Any]] = pydantic_v1.Field(default=None) + filter: typing.Optional[WebhookFilter] = pydantic.Field(default=None) """ - Filter for selecting which events you want Webhooks to be sent for. Only supported for form_submission trigger types. + Only supported for the `form_submission` trigger type. Filter for the form you want Webhooks to be sent for. """ - last_triggered: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="lastTriggered", default=None) + last_triggered: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastTriggered")] = ( + pydantic.Field(default=None) + ) """ Date the Webhook instance was last triggered """ - created_on: typing.Optional[dt.datetime] = pydantic_v1.Field(alias="createdOn", default=None) + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( + pydantic.Field(default=None) + ) """ Date the Webhook registration was created """ - url: typing.Optional[str] = pydantic_v1.Field(default=None) - """ - URL to send the Webhook payload to - """ - - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - allow_population_by_field_name = True - populate_by_name = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/webhook_filter.py b/src/webflow/types/webhook_filter.py new file mode 100644 index 0000000..ccffba5 --- /dev/null +++ b/src/webflow/types/webhook_filter.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class WebhookFilter(UniversalBaseModel): + """ + Only supported for the `form_submission` trigger type. Filter for the form you want Webhooks to be sent for. + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + The name of the form you'd like to recieve notifications for. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/webhook_list.py b/src/webflow/types/webhook_list.py index d55f417..ea705c4 100644 --- a/src/webflow/types/webhook_list.py +++ b/src/webflow/types/webhook_list.py @@ -1,32 +1,22 @@ # This file was auto-generated by Fern from our API Definition. -import datetime as dt +from ..core.pydantic_utilities import UniversalBaseModel import typing - -from ..core.datetime_utils import serialize_datetime -from ..core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1 from .pagination import Pagination from .webhook import Webhook +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic -class WebhookList(pydantic_v1.BaseModel): +class WebhookList(UniversalBaseModel): pagination: typing.Optional[Pagination] = None webhooks: typing.Optional[typing.List[Webhook]] = None - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - return super().json(**kwargs_with_defaults) - - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: - kwargs_with_defaults_exclude_unset: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs} - kwargs_with_defaults_exclude_none: typing.Any = {"by_alias": True, "exclude_none": True, **kwargs} - - return deep_union_pydantic_dicts( - super().dict(**kwargs_with_defaults_exclude_unset), super().dict(**kwargs_with_defaults_exclude_none) - ) + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: - class Config: - frozen = True - smart_union = True - extra = pydantic_v1.Extra.allow - json_encoders = {dt.datetime: serialize_datetime} + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/version.py b/src/webflow/version.py index c84c3e9..f29b4ca 100644 --- a/src/webflow/version.py +++ b/src/webflow/version.py @@ -1,4 +1,3 @@ - from importlib import metadata __version__ = metadata.version("webflow") diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..f3ea265 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/tests/collections/__init__.py b/tests/collections/__init__.py new file mode 100644 index 0000000..f3ea265 --- /dev/null +++ b/tests/collections/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/tests/collections/test_fields.py b/tests/collections/test_fields.py new file mode 100644 index 0000000..f64c447 --- /dev/null +++ b/tests/collections/test_fields.py @@ -0,0 +1,97 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response + + +async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "75821f618da60c18383330bcc0ca488b", + "isRequired": False, + "isEditable": True, + "type": "RichText", + "slug": "post-body", + "displayName": "Post Body", + "helpText": "Add the body of your post here", + } + expected_types: typing.Any = { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + } + response = client.collections.fields.create( + collection_id="580e63fc8c9a982ac9b8b745", + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.fields.create( + collection_id="580e63fc8c9a982ac9b8b745", + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.collections.fields.delete(collection_id="580e63fc8c9a982ac9b8b745", field_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.collections.fields.delete( + collection_id="580e63fc8c9a982ac9b8b745", field_id="580e63fc8c9a982ac9b8b745" + ) # type: ignore[func-returns-value] + is None + ) + + +async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "75821f618da60c18383330bcc0ca488b", + "isRequired": False, + "isEditable": True, + "type": "RichText", + "slug": "post-body", + "displayName": "Post Body", + "helpText": "Add the body of your post here", + } + expected_types: typing.Any = { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + } + response = client.collections.fields.update( + collection_id="580e63fc8c9a982ac9b8b745", + field_id="580e63fc8c9a982ac9b8b745", + is_required=False, + display_name="Post Body", + help_text="Add the body of your post here", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.fields.update( + collection_id="580e63fc8c9a982ac9b8b745", + field_id="580e63fc8c9a982ac9b8b745", + is_required=False, + display_name="Post Body", + help_text="Add the body of your post here", + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/collections/test_items.py b/tests/collections/test_items.py new file mode 100644 index 0000000..fc926a7 --- /dev/null +++ b/tests/collections/test_items.py @@ -0,0 +1,810 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response +from webflow import CollectionItemPostSingle +from webflow import CollectionItemPostSingleFieldData +from webflow import CollectionItemWithIdInput +from webflow import CollectionItemWithIdInputFieldData +from webflow import CollectionItem +from webflow import CollectionItemFieldData +from webflow.resources.collections.resources.items import SingleCmsItem +from webflow import CollectionItemPatchSingleFieldData + + +async def test_list_items(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "items": [ + { + "id": "62b720ef280c7a7a3be8cabe", + "cmsLocaleId": "66f6e966c9e1dc700a857ca3", + "lastPublished": "2022-06-30T13:35:20.878Z", + "lastUpdated": "2022-06-25T14:51:27.809Z", + "createdOn": "2022-06-25T14:51:27.809Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Senior Data Analyst", + "slug": "senior-data-analyst", + "url": "https://boards.greenhouse.io/webflow/jobs/26567701", + "department": "Data", + }, + }, + { + "id": "62c880ef281c7b7b4cf9dabc", + "cmsLocaleId": "66f6e966c9e1dc700a857ca3", + "lastPublished": "2023-04-15T10:25:18.123Z", + "lastUpdated": "2023-04-10T11:45:30.567Z", + "createdOn": "2023-04-10T11:45:30.567Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Product Manager", + "slug": "product-manager", + "url": "https://boards.greenhouse.io/webflow/jobs/31234567", + "department": "Product", + }, + }, + ], + "pagination": {"limit": 25, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "items": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + 1: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.collections.items.list_items(collection_id="580e63fc8c9a982ac9b8b745") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.list_items(collection_id="580e63fc8c9a982ac9b8b745") + validate_response(async_response, expected_response, expected_types) + + +async def test_create_item(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "42b720ef280c7a7a3be8cabe", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2022-11-29T16:22:43.159Z", + "lastUpdated": "2022-11-17T17:19:43.282Z", + "createdOn": "2022-11-17T17:11:57.148Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Pan Galactic Gargle Blaster Recipe", + "slug": "pan-galactic-gargle-blaster", + "color": "#db4b68", + "date": "2022-11-18T00:00:00.000Z", + "featured": True, + }, + } + expected_types: typing.Any = { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + } + response = client.collections.items.create_item( + collection_id="580e63fc8c9a982ac9b8b745", + request=CollectionItemPostSingle( + is_archived=False, + is_draft=False, + field_data=CollectionItemPostSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + ), + ), + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.create_item( + collection_id="580e63fc8c9a982ac9b8b745", + request=CollectionItemPostSingle( + is_archived=False, + is_draft=False, + field_data=CollectionItemPostSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + ), + ), + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete_items(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.collections.items.delete_items(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.collections.items.delete_items(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + is None + ) + + +async def test_update_items(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "id", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2023-03-17T18:47:35.560Z", + "lastUpdated": "2023-03-17T18:47:35.560Z", + "createdOn": "2023-03-17T18:47:35.560Z", + "isArchived": True, + "isDraft": True, + "fieldData": { + "name": "My new item", + "slug": "my-new-item", + "date": "2022-11-18T00:00:00.000Z", + "featured": False, + "color": "#db4b68", + }, + } + expected_types: typing.Any = { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + } + response = client.collections.items.update_items( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData(name="Ne Paniquez Pas", slug="ne-paniquez-pas"), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData(name="No Entrar en Pánico", slug="no-entrar-en-panico"), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Au Revoir et Merci pour Tous les Poissons", slug="au-revoir-et-merci" + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="Hasta Luego y Gracias por Todo el Pescado", slug="hasta-luego-y-gracias" + ), + ), + ], + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.update_items( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData(name="Ne Paniquez Pas", slug="ne-paniquez-pas"), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData(name="No Entrar en Pánico", slug="no-entrar-en-panico"), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Au Revoir et Merci pour Tous les Poissons", slug="au-revoir-et-merci" + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="Hasta Luego y Gracias por Todo el Pescado", slug="hasta-luego-y-gracias" + ), + ), + ], + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_list_items_live(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "items": [ + { + "id": "62b720ef280c7a7a3be8cabe", + "cmsLocaleId": "66f6e966c9e1dc700a857ca3", + "lastPublished": "2022-06-30T13:35:20.878Z", + "lastUpdated": "2022-06-25T14:51:27.809Z", + "createdOn": "2022-06-25T14:51:27.809Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Senior Data Analyst", + "slug": "senior-data-analyst", + "url": "https://boards.greenhouse.io/webflow/jobs/26567701", + "department": "Data", + }, + }, + { + "id": "62c880ef281c7b7b4cf9dabc", + "cmsLocaleId": "66f6e966c9e1dc700a857ca3", + "lastPublished": "2023-04-15T10:25:18.123Z", + "lastUpdated": "2023-04-10T11:45:30.567Z", + "createdOn": "2023-04-10T11:45:30.567Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Product Manager", + "slug": "product-manager", + "url": "https://boards.greenhouse.io/webflow/jobs/31234567", + "department": "Product", + }, + }, + ], + "pagination": {"limit": 25, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "items": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + 1: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.collections.items.list_items_live(collection_id="580e63fc8c9a982ac9b8b745") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.list_items_live(collection_id="580e63fc8c9a982ac9b8b745") + validate_response(async_response, expected_response, expected_types) + + +async def test_create_item_live(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "42b720ef280c7a7a3be8cabe", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2022-11-29T16:22:43.159Z", + "lastUpdated": "2022-11-17T17:19:43.282Z", + "createdOn": "2022-11-17T17:11:57.148Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Pan Galactic Gargle Blaster Recipe", + "slug": "pan-galactic-gargle-blaster", + "color": "#db4b68", + "date": "2022-11-18T00:00:00.000Z", + "featured": True, + }, + } + expected_types: typing.Any = { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + } + response = client.collections.items.create_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + request=CollectionItem( + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + ), + ), + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.create_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + request=CollectionItem( + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + ), + ), + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete_items_live(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.collections.items.delete_items_live(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.collections.items.delete_items_live(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + is None + ) + + +async def test_update_items_live(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "items": [ + { + "id": "66f6ed9576ddacf3149d5ea6", + "cmsLocaleId": "66f6e966c9e1dc700a857ca5", + "lastPublished": "2023-03-17T18:47:35.560Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": True, + "isDraft": True, + "fieldData": {"name": "Ne Paniquez Pas", "slug": "ne-paniquez-pas", "featured": False}, + }, + { + "id": "66f6ed9576ddacf3149d5ea6", + "cmsLocaleId": "66f6e966c9e1dc700a857ca4", + "lastPublished": "2023-03-17T18:47:35.560Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": True, + "isDraft": True, + "fieldData": {"name": "No Entrar en Pánico", "slug": "no-entrar-en-panico", "featured": False}, + }, + { + "id": "66f6ed9576ddacf3149d5eaa", + "cmsLocaleId": "66f6e966c9e1dc700a857ca5", + "lastPublished": "2023-03-17T18:47:35.560Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": True, + "isDraft": True, + "fieldData": { + "name": "Au Revoir et Merci pour Tous les Poissons", + "slug": "au-revoir-et-merci", + "featured": False, + }, + }, + { + "id": "66f6ed9576ddacf3149d5eaa", + "cmsLocaleId": "66f6e966c9e1dc700a857ca4", + "lastPublished": "2023-03-17T18:47:35.560Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": True, + "isDraft": True, + "fieldData": { + "name": "Hasta Luego y Gracias por Todo el Pescado", + "slug": "hasta-luego-y-gracias", + "featured": False, + }, + }, + ] + } + expected_types: typing.Any = { + "items": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + 1: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + 2: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + 3: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + }, + ) + } + response = client.collections.items.update_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData(name="Ne Paniquez Pas", slug="ne-paniquez-pas"), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData(name="No Entrar en Pánico", slug="no-entrar-en-panico"), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Au Revoir et Merci pour Tous les Poissons", slug="au-revoir-et-merci" + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="Hasta Luego y Gracias por Todo el Pescado", slug="hasta-luego-y-gracias" + ), + ), + ], + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.update_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData(name="Ne Paniquez Pas", slug="ne-paniquez-pas"), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData(name="No Entrar en Pánico", slug="no-entrar-en-panico"), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Au Revoir et Merci pour Tous les Poissons", slug="au-revoir-et-merci" + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="Hasta Luego y Gracias por Todo el Pescado", slug="hasta-luego-y-gracias" + ), + ), + ], + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_create_items(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "580e64008c9a982ac9b8b754", + "cmsLocaleIds": ["653ad57de882f528b32e810e", "6514390aea353fc691d69827", "65143930ea353fc691d69cd8"], + "lastPublished": "2023-03-17T18:47:35.560Z", + "lastUpdated": "2023-03-17T18:47:35.560Z", + "createdOn": "2023-03-17T18:47:35.560Z", + "isArchived": True, + "isDraft": True, + "fieldData": { + "name": "My new item", + "slug": "my-new-item", + "date": "2022-11-18T00:00:00.000Z", + "featured": False, + "color": "#db4b68", + }, + } + expected_types: typing.Any = { + "id": None, + "cmsLocaleIds": ("list", {0: None, 1: None, 2: None}), + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + } + response = client.collections.items.create_items( + collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_ids=["66f6e966c9e1dc700a857ca3", "66f6e966c9e1dc700a857ca4", "66f6e966c9e1dc700a857ca5"], + is_archived=False, + is_draft=False, + field_data=SingleCmsItem(name="Don’t Panic", slug="dont-panic"), + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.create_items( + collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_ids=["66f6e966c9e1dc700a857ca3", "66f6e966c9e1dc700a857ca4", "66f6e966c9e1dc700a857ca5"], + is_archived=False, + is_draft=False, + field_data=SingleCmsItem(name="Don’t Panic", slug="dont-panic"), + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get_item(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "42b720ef280c7a7a3be8cabe", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2022-11-29T16:22:43.159Z", + "lastUpdated": "2022-11-17T17:19:43.282Z", + "createdOn": "2022-11-17T17:11:57.148Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Pan Galactic Gargle Blaster Recipe", + "slug": "pan-galactic-gargle-blaster", + "color": "#db4b68", + "date": "2022-11-18T00:00:00.000Z", + "featured": True, + }, + } + expected_types: typing.Any = { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + } + response = client.collections.items.get_item( + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.get_item( + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete_item(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.collections.items.delete_item( + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + ) # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.collections.items.delete_item( + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + ) # type: ignore[func-returns-value] + is None + ) + + +async def test_update_item(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "42b720ef280c7a7a3be8cabe", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2022-11-29T16:22:43.159Z", + "lastUpdated": "2022-11-17T17:19:43.282Z", + "createdOn": "2022-11-17T17:11:57.148Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Pan Galactic Gargle Blaster Recipe", + "slug": "pan-galactic-gargle-blaster", + "color": "#db4b68", + "date": "2022-11-18T00:00:00.000Z", + "featured": True, + }, + } + expected_types: typing.Any = { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + } + response = client.collections.items.update_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, + field_data=CollectionItemPatchSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + ), + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.update_item( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, + field_data=CollectionItemPatchSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + ), + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get_item_live(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "42b720ef280c7a7a3be8cabe", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2022-11-29T16:22:43.159Z", + "lastUpdated": "2022-11-17T17:19:43.282Z", + "createdOn": "2022-11-17T17:11:57.148Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Pan Galactic Gargle Blaster Recipe", + "slug": "pan-galactic-gargle-blaster", + "color": "#db4b68", + "date": "2022-11-18T00:00:00.000Z", + "featured": True, + }, + } + expected_types: typing.Any = { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + } + response = client.collections.items.get_item_live( + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.get_item_live( + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete_item_live(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.collections.items.delete_item_live( + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + ) # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.collections.items.delete_item_live( + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + ) # type: ignore[func-returns-value] + is None + ) + + +async def test_update_item_live(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "42b720ef280c7a7a3be8cabe", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2022-11-29T16:22:43.159Z", + "lastUpdated": "2022-11-17T17:19:43.282Z", + "createdOn": "2022-11-17T17:11:57.148Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Pan Galactic Gargle Blaster Recipe", + "slug": "pan-galactic-gargle-blaster", + "color": "#db4b68", + "date": "2022-11-18T00:00:00.000Z", + "featured": True, + }, + } + expected_types: typing.Any = { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + } + response = client.collections.items.update_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, + field_data=CollectionItemPatchSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + ), + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.update_item_live( + collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, + field_data=CollectionItemPatchSingleFieldData( + name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + ), + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_publish_item(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "publishedItemIds": ["643fd856d66b6528195ee2ca", "643fd856d66b6528195ee2cb"], + "errors": ["Staging item ID 643fd856d66b6528195ee2cf not found."], + } + expected_types: typing.Any = {"publishedItemIds": ("list", {0: None, 1: None}), "errors": ("list", {0: None})} + response = client.collections.items.publish_item(collection_id="580e63fc8c9a982ac9b8b745", item_ids=["itemIds"]) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.items.publish_item( + collection_id="580e63fc8c9a982ac9b8b745", item_ids=["itemIds"] + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..019aab8 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +import os +import pytest +from webflow import AsyncWebflow + + +@pytest.fixture +def client() -> Webflow: + return Webflow( + access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), base_url=os.getenv("TESTS_BASE_URL", "base_url") + ) + + +@pytest.fixture +def async_client() -> AsyncWebflow: + return AsyncWebflow( + access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), base_url=os.getenv("TESTS_BASE_URL", "base_url") + ) diff --git a/tests/custom/test_client.py b/tests/custom/test_client.py index 60a58e6..73f811f 100644 --- a/tests/custom/test_client.py +++ b/tests/custom/test_client.py @@ -1,5 +1,6 @@ import pytest + # Get started with writing tests with pytest at https://docs.pytest.org @pytest.mark.skip(reason="Unimplemented") def test_client() -> None: diff --git a/tests/pages/__init__.py b/tests/pages/__init__.py new file mode 100644 index 0000000..f3ea265 --- /dev/null +++ b/tests/pages/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/tests/pages/test_scripts.py b/tests/pages/test_scripts.py new file mode 100644 index 0000000..0e553d2 --- /dev/null +++ b/tests/pages/test_scripts.py @@ -0,0 +1,85 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response +from webflow import ScriptApply + + +async def test_get_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "scripts": [{"id": "id", "location": "header", "version": "version", "attributes": {"key": "value"}}], + "lastUpdated": "lastUpdated", + "createdOn": "createdOn", + } + expected_types: typing.Any = { + "scripts": ( + "list", + {0: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}}, + ), + "lastUpdated": None, + "createdOn": None, + } + response = client.pages.scripts.get_custom_code(page_id="63c720f9347c2139b248e552") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.pages.scripts.get_custom_code(page_id="63c720f9347c2139b248e552") + validate_response(async_response, expected_response, expected_types) + + +async def test_upsert_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "scripts": [ + { + "id": "cms_slider", + "location": "header", + "version": "1.0.0", + "attributes": {"my-attribute": "some-value"}, + }, + {"id": "alert", "location": "header", "version": "0.0.1", "attributes": {"key": "value"}}, + ], + "lastUpdated": "2022-10-26T00:28:54.191Z", + "createdOn": "2022-10-26T00:28:54.191Z", + } + expected_types: typing.Any = { + "scripts": ( + "list", + { + 0: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, + 1: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, + }, + ), + "lastUpdated": None, + "createdOn": None, + } + response = client.pages.scripts.upsert_custom_code( + page_id="63c720f9347c2139b248e552", + scripts=[ + ScriptApply(id="cms_slider", location="header", version="1.0.0", attributes={"my-attribute": "some-value"}), + ScriptApply(id="alert", location="header", version="0.0.1"), + ], + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.pages.scripts.upsert_custom_code( + page_id="63c720f9347c2139b248e552", + scripts=[ + ScriptApply(id="cms_slider", location="header", version="1.0.0", attributes={"my-attribute": "some-value"}), + ScriptApply(id="alert", location="header", version="0.0.1"), + ], + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.pages.scripts.delete_custom_code(page_id="63c720f9347c2139b248e552") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.pages.scripts.delete_custom_code(page_id="63c720f9347c2139b248e552") # type: ignore[func-returns-value] + is None + ) diff --git a/tests/sites/__init__.py b/tests/sites/__init__.py new file mode 100644 index 0000000..f3ea265 --- /dev/null +++ b/tests/sites/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/tests/sites/test_activity_logs.py b/tests/sites/test_activity_logs.py new file mode 100644 index 0000000..f289464 --- /dev/null +++ b/tests/sites/test_activity_logs.py @@ -0,0 +1,53 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "items": [ + { + "id": "654c16c7b229e56bcf26872d", + "createdOn": "2023-11-08T23:16:23Z", + "lastUpdated": "2023-11-08T23:16:23Z", + "event": "cms_collection", + "resourceOperation": "CREATED", + "user": {"id": "6509cd56e90eec668b009712", "displayName": "John Doe"}, + "resourceId": "654c16c7b229e56bcf26870c", + "resourceName": "foo-bar", + "newValue": "newValue", + "previousValue": "previousValue", + "payload": {"key": "value"}, + } + ], + "pagination": {"limit": 25, "offset": 0, "total": 1}, + } + expected_types: typing.Any = { + "items": ( + "list", + { + 0: { + "id": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + "event": None, + "resourceOperation": None, + "user": {"id": None, "displayName": None}, + "resourceId": None, + "resourceName": None, + "newValue": None, + "previousValue": None, + "payload": ("dict", {0: (None, None)}), + } + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.sites.activity_logs.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.activity_logs.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_plans.py b/tests/sites/test_plans.py new file mode 100644 index 0000000..01c304e --- /dev/null +++ b/tests/sites/test_plans.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response + + +async def test_get_site_plan(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "hosting-business-v4", + "name": "Business Hosting", + "pricingInfo": "https://webflow.com/pricing", + } + expected_types: typing.Any = {"id": None, "name": None, "pricingInfo": None} + response = client.sites.plans.get_site_plan(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.plans.get_site_plan(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_redirects.py b/tests/sites/test_redirects.py new file mode 100644 index 0000000..e10b50e --- /dev/null +++ b/tests/sites/test_redirects.py @@ -0,0 +1,88 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "redirects": [ + {"id": "42e1a2b7aa1a13f768a0042a", "fromUrl": "/mostly-harmless", "toUrl": "/earth"}, + {"id": "6x9e7f8d9a4b1c2d3e4f5678", "fromUrl": "/babel-fish", "toUrl": "/translate"}, + ], + "pagination": {"limit": 100, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "redirects": ( + "list", + {0: {"id": None, "fromUrl": None, "toUrl": None}, 1: {"id": None, "fromUrl": None, "toUrl": None}}, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.sites.redirects.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.redirects.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = {"id": "42e1a2b7aa1a13f768a0042a", "fromUrl": "/mostly-harmless", "toUrl": "/earth"} + expected_types: typing.Any = {"id": None, "fromUrl": None, "toUrl": None} + response = client.sites.redirects.create( + site_id="580e63e98c9a982ac9b8b741", id="42e1a2b7aa1a13f768a0042a", from_url="/mostly-harmless", to_url="/earth" + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.redirects.create( + site_id="580e63e98c9a982ac9b8b741", id="42e1a2b7aa1a13f768a0042a", from_url="/mostly-harmless", to_url="/earth" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "redirects": [ + {"id": "42e1a2b7aa1a13f768a0042a", "fromUrl": "/mostly-harmless", "toUrl": "/earth"}, + {"id": "6x9e7f8d9a4b1c2d3e4f5678", "fromUrl": "/babel-fish", "toUrl": "/translate"}, + ], + "pagination": {"limit": 100, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "redirects": ( + "list", + {0: {"id": None, "fromUrl": None, "toUrl": None}, 1: {"id": None, "fromUrl": None, "toUrl": None}}, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.sites.redirects.delete(site_id="580e63e98c9a982ac9b8b741", redirect_id="66c4cb9a20cac35ed19500e6") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.redirects.delete( + site_id="580e63e98c9a982ac9b8b741", redirect_id="66c4cb9a20cac35ed19500e6" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = {"id": "42e1a2b7aa1a13f768a0042a", "fromUrl": "/mostly-harmless", "toUrl": "/earth"} + expected_types: typing.Any = {"id": None, "fromUrl": None, "toUrl": None} + response = client.sites.redirects.update( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", + id="42e1a2b7aa1a13f768a0042a", + from_url="/mostly-harmless", + to_url="/earth", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.redirects.update( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", + id="42e1a2b7aa1a13f768a0042a", + from_url="/mostly-harmless", + to_url="/earth", + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_scripts.py b/tests/sites/test_scripts.py new file mode 100644 index 0000000..cc5d71c --- /dev/null +++ b/tests/sites/test_scripts.py @@ -0,0 +1,154 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response +from webflow import ScriptApply + + +async def test_get_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "scripts": [ + { + "id": "cms_slider", + "location": "header", + "version": "1.0.0", + "attributes": {"my-attribute": "some-value"}, + }, + {"id": "alert", "location": "header", "version": "0.0.1", "attributes": {"key": "value"}}, + ], + "lastUpdated": "2022-10-26T00:28:54.191Z", + "createdOn": "2022-10-26T00:28:54.191Z", + } + expected_types: typing.Any = { + "scripts": ( + "list", + { + 0: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, + 1: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, + }, + ), + "lastUpdated": None, + "createdOn": None, + } + response = client.sites.scripts.get_custom_code(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.scripts.get_custom_code(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_upsert_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "scripts": [ + { + "id": "cms_slider", + "location": "header", + "version": "1.0.0", + "attributes": {"my-attribute": "some-value"}, + }, + {"id": "alert", "location": "header", "version": "0.0.1", "attributes": {"key": "value"}}, + ], + "lastUpdated": "lastUpdated", + "createdOn": "createdOn", + } + expected_types: typing.Any = { + "scripts": ( + "list", + { + 0: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, + 1: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, + }, + ), + "lastUpdated": None, + "createdOn": None, + } + response = client.sites.scripts.upsert_custom_code( + site_id="580e63e98c9a982ac9b8b741", + scripts=[ + ScriptApply(id="cms_slider", location="header", version="1.0.0", attributes={"my-attribute": "some-value"}), + ScriptApply(id="alert", location="header", version="0.0.1"), + ], + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.scripts.upsert_custom_code( + site_id="580e63e98c9a982ac9b8b741", + scripts=[ + ScriptApply(id="cms_slider", location="header", version="1.0.0", attributes={"my-attribute": "some-value"}), + ScriptApply(id="alert", location="header", version="0.0.1"), + ], + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.sites.scripts.delete_custom_code(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.sites.scripts.delete_custom_code(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + +async def test_list_custom_code_blocks(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "blocks": [ + { + "siteId": "6258612d1ee792848f805dcf", + "pageId": "pageId", + "type": "site", + "scripts": [ + {"id": "chartjs", "location": "header", "version": "4.4.2", "attributes": {"key": "value"}} + ], + "createdOn": "2024-04-03T16:49:15Z", + "lastUpdated": "2024-04-03T16:49:15Z", + }, + { + "siteId": "6390c49674a71f84b51a08d8", + "pageId": "6419db964a9c43f6a3af6348", + "type": "page", + "scripts": [{"id": "id", "location": "header", "version": "version"}], + "createdOn": "2022-10-26T00:28:54Z", + "lastUpdated": "2022-10-26T00:28:54Z", + }, + ], + "pagination": {"limit": 10, "offset": 0, "total": 1}, + } + expected_types: typing.Any = { + "blocks": ( + "list", + { + 0: { + "siteId": None, + "pageId": None, + "type": None, + "scripts": ( + "list", + {0: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}}, + ), + "createdOn": "datetime", + "lastUpdated": "datetime", + }, + 1: { + "siteId": None, + "pageId": None, + "type": None, + "scripts": ("list", {0: {"id": None, "location": None, "version": None}}), + "createdOn": "datetime", + "lastUpdated": "datetime", + }, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.sites.scripts.list_custom_code_blocks(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.scripts.list_custom_code_blocks(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_access_groups.py b/tests/test_access_groups.py new file mode 100644 index 0000000..dfe7e19 --- /dev/null +++ b/tests/test_access_groups.py @@ -0,0 +1,49 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "count": 1, + "limit": 10, + "offset": 0, + "total": 1, + "accessGroups": [ + { + "id": "62be58d404be8a6cc900c081", + "name": "Research Team", + "shortId": "rt", + "slug": "hitchhikers-guide-research-team", + "createdOn": "2022-08-01T19:41:48Z", + }, + { + "id": "65a96161991e77bbb4a6c573", + "name": "Admin", + "shortId": "ad", + "slug": "admin", + "createdOn": "2022-08-01T19:41:48Z", + }, + ], + } + expected_types: typing.Any = { + "count": None, + "limit": None, + "offset": None, + "total": None, + "accessGroups": ( + "list", + { + 0: {"id": None, "name": None, "shortId": None, "slug": None, "createdOn": "datetime"}, + 1: {"id": None, "name": None, "shortId": None, "slug": None, "createdOn": "datetime"}, + }, + ), + } + response = client.access_groups.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.access_groups.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_assets.py b/tests/test_assets.py new file mode 100644 index 0000000..af158ef --- /dev/null +++ b/tests/test_assets.py @@ -0,0 +1,358 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "assets": [ + { + "id": "63e5889e7fe4eafa7384cea4", + "contentType": "image/png", + "size": 2212772, + "siteId": "63938b302ea6b0aa6f3d8745", + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg", + "originalFileName": "Candy-Wrapper.svg", + "displayName": "63e5889e7fe4eafa7384cea4_Candy-Wrapper.png", + "lastUpdated": "2023-03-01T23:42:57Z", + "createdOn": "2023-02-09T23:58:22Z", + "variants": [ + { + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "originalFileName": "Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "displayName": "660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "format": "png", + "width": 500, + "height": 900, + "quality": 100, + } + ], + "altText": "A red chair", + } + ] + } + expected_types: typing.Any = { + "assets": ( + "list", + { + 0: { + "id": None, + "contentType": None, + "size": "integer", + "siteId": None, + "hostedUrl": None, + "originalFileName": None, + "displayName": None, + "lastUpdated": "datetime", + "createdOn": "datetime", + "variants": ( + "list", + { + 0: { + "hostedUrl": None, + "originalFileName": None, + "displayName": None, + "format": None, + "width": "integer", + "height": "integer", + "quality": "integer", + } + }, + ), + "altText": None, + } + }, + ) + } + response = client.assets.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.assets.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "uploadDetails": { + "acl": "public-read", + "bucket": "webflow-bucket-name", + "X-Amz-Algorithm": "AWS4-HMAC-SHA256", + "X-Amz-Credential": "///s3/aws4_request", + "X-Amz-Date": "", + "key": "/_", + "Policy": "", + "X-Amz-Signature": "", + "success_action_status": "201", + "content-type": "image/png", + "Cache-Control": "max-age=31536000, must-revalidate", + }, + "contentType": "image/png", + "id": "64358b9544249dc43d37d2b7", + "parentFolder": "6436b1ce5281cace05b65aea", + "uploadUrl": "https://s3.amazonaws.com/webflow-dev-assets/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png", + "assetUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d907ab9e91e3e9f56385e_paranoidAndroid-2024.png", + "hostedUrl": "https://d1otoma47x30pg.cloudfront.net/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png", + "originalFileName": "file.png", + "createdOn": "2023-04-11T16:32:21Z", + "lastUpdated": "2023-04-12T20:31:03Z", + } + expected_types: typing.Any = { + "uploadDetails": { + "acl": None, + "bucket": None, + "X-Amz-Algorithm": None, + "X-Amz-Credential": None, + "X-Amz-Date": None, + "key": None, + "Policy": None, + "X-Amz-Signature": None, + "success_action_status": None, + "content-type": None, + "Cache-Control": None, + }, + "contentType": None, + "id": None, + "parentFolder": None, + "uploadUrl": None, + "assetUrl": None, + "hostedUrl": None, + "originalFileName": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + } + response = client.assets.create( + site_id="580e63e98c9a982ac9b8b741", file_name="file.png", file_hash="3c7d87c9575702bc3b1e991f4d3c638e" + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.assets.create( + site_id="580e63e98c9a982ac9b8b741", file_name="file.png", file_hash="3c7d87c9575702bc3b1e991f4d3c638e" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "55131cd036c09f7d07883dfc", + "contentType": "image/png", + "size": 1500, + "siteId": "62749158efef318abc8d5a0f", + "hostedUrl": "example.com/hostedimage.png", + "originalFileName": "image.png", + "displayName": "example-image-123.png", + "lastUpdated": "2016-09-06T21:12:22Z", + "createdOn": "2016-09-02T23:26:22Z", + "variants": [ + { + "hostedUrl": "example.com/hostedimage.png", + "originalFileName": "image.png", + "displayName": "A brown dog", + "format": "format", + "width": 1500, + "height": 900, + "quality": 1, + "error": "error", + } + ], + "altText": "A red chair", + } + expected_types: typing.Any = { + "id": None, + "contentType": None, + "size": "integer", + "siteId": None, + "hostedUrl": None, + "originalFileName": None, + "displayName": None, + "lastUpdated": "datetime", + "createdOn": "datetime", + "variants": ( + "list", + { + 0: { + "hostedUrl": None, + "originalFileName": None, + "displayName": None, + "format": None, + "width": "integer", + "height": "integer", + "quality": "integer", + "error": None, + } + }, + ), + "altText": None, + } + response = client.assets.get(asset_id="580e63fc8c9a982ac9b8b745") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.assets.get(asset_id="580e63fc8c9a982ac9b8b745") + validate_response(async_response, expected_response, expected_types) + + +async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.assets.delete(asset_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.assets.delete(asset_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + is None + ) + + +async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "55131cd036c09f7d07883dfc", + "contentType": "image/png", + "size": 1500, + "siteId": "62749158efef318abc8d5a0f", + "hostedUrl": "example.com/hostedimage.png", + "originalFileName": "image.png", + "displayName": "example-image-123.png", + "lastUpdated": "2016-09-06T21:12:22Z", + "createdOn": "2016-09-02T23:26:22Z", + "variants": [ + { + "hostedUrl": "example.com/hostedimage.png", + "originalFileName": "image.png", + "displayName": "A brown dog", + "format": "format", + "width": 1500, + "height": 900, + "quality": 1, + "error": "error", + } + ], + "altText": "A red chair", + } + expected_types: typing.Any = { + "id": None, + "contentType": None, + "size": "integer", + "siteId": None, + "hostedUrl": None, + "originalFileName": None, + "displayName": None, + "lastUpdated": "datetime", + "createdOn": "datetime", + "variants": ( + "list", + { + 0: { + "hostedUrl": None, + "originalFileName": None, + "displayName": None, + "format": None, + "width": "integer", + "height": "integer", + "quality": "integer", + "error": None, + } + }, + ), + "altText": None, + } + response = client.assets.update(asset_id="580e63fc8c9a982ac9b8b745") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.assets.update(asset_id="580e63fc8c9a982ac9b8b745") + validate_response(async_response, expected_response, expected_types) + + +async def test_list_folders(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "assetFolders": [ + { + "id": "6390c49774a71f0e3c1a08ee", + "displayName": "emoji icons", + "parentFolder": "6390c49774a71f99f21a08eb", + "assets": ["63e5889e7fe4eafa7384cea4", "659595234426a9fcbad57043"], + "siteId": "6390c49674a71f84b51a08d8", + "createdOn": "2018-10-14T21:55:49Z", + "lastUpdated": "2022-12-07T16:51:37Z", + } + ], + "pagination": {"limit": 1, "offset": 0, "total": 1}, + } + expected_types: typing.Any = { + "assetFolders": ( + "list", + { + 0: { + "id": None, + "displayName": None, + "parentFolder": None, + "assets": ("list", {0: None, 1: None}), + "siteId": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + } + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.assets.list_folders(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.assets.list_folders(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_create_folder(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "6390c49774a71f0e3c1a08ee", + "displayName": "emoji icons", + "parentFolder": "6390c49774a71f99f21a08eb", + "assets": ["63e5889e7fe4eafa7384cea4", "659595234426a9fcbad57043"], + "siteId": "6390c49674a71f84b51a08d8", + "createdOn": "2018-10-14T21:55:49Z", + "lastUpdated": "2022-12-07T16:51:37Z", + } + expected_types: typing.Any = { + "id": None, + "displayName": None, + "parentFolder": None, + "assets": ("list", {0: None, 1: None}), + "siteId": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + } + response = client.assets.create_folder(site_id="580e63e98c9a982ac9b8b741", display_name="my asset folder") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.assets.create_folder( + site_id="580e63e98c9a982ac9b8b741", display_name="my asset folder" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get_folder(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "6390c49774a71f0e3c1a08ee", + "displayName": "emoji icons", + "parentFolder": "6390c49774a71f99f21a08eb", + "assets": ["63e5889e7fe4eafa7384cea4", "659595234426a9fcbad57043"], + "siteId": "6390c49674a71f84b51a08d8", + "createdOn": "2018-10-14T21:55:49Z", + "lastUpdated": "2022-12-07T16:51:37Z", + } + expected_types: typing.Any = { + "id": None, + "displayName": None, + "parentFolder": None, + "assets": ("list", {0: None, 1: None}), + "siteId": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + } + response = client.assets.get_folder(asset_folder_id="6390c49774a71f0e3c1a08ee") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.assets.get_folder(asset_folder_id="6390c49774a71f0e3c1a08ee") + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_collections.py b/tests/test_collections.py new file mode 100644 index 0000000..1e76945 --- /dev/null +++ b/tests/test_collections.py @@ -0,0 +1,188 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "collections": [ + { + "id": "63692ab61fb2852f582ba8f5", + "displayName": "Products", + "singularName": "Product", + "slug": "product", + "createdOn": "2019-06-12T13:35:14Z", + "lastUpdated": "2022-11-17T15:08:50Z", + }, + { + "id": "63692ab61fb2856e6a2ba8f6", + "displayName": "Categories", + "singularName": "Category", + "slug": "category", + "createdOn": "2019-06-12T13:35:14Z", + "lastUpdated": "2022-11-17T15:08:50Z", + }, + { + "id": "63692ab61fb285a8562ba8f4", + "displayName": "SKUs", + "singularName": "SKU", + "slug": "sku", + "createdOn": "2019-06-12T13:35:14Z", + "lastUpdated": "2022-11-17T15:08:50Z", + }, + ] + } + expected_types: typing.Any = { + "collections": ( + "list", + { + 0: { + "id": None, + "displayName": None, + "singularName": None, + "slug": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + }, + 1: { + "id": None, + "displayName": None, + "singularName": None, + "slug": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + }, + 2: { + "id": None, + "displayName": None, + "singularName": None, + "slug": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + }, + }, + ) + } + response = client.collections.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "580e63fc8c9a982ac9b8b745", + "displayName": "Blog Posts", + "singularName": "Blog Post", + "slug": "post", + "createdOn": "2016-10-24T19:41:48Z", + "lastUpdated": "2016-10-24T19:42:38Z", + "fields": [ + { + "id": "23cc2d952d4e4631ffd4345d2743db4e", + "isRequired": True, + "isEditable": True, + "type": "PlainText", + "slug": "name", + "displayName": "Name", + "helpText": "helpText", + } + ], + } + expected_types: typing.Any = { + "id": None, + "displayName": None, + "singularName": None, + "slug": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + "fields": ( + "list", + { + 0: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + } + }, + ), + } + response = client.collections.create( + site_id="580e63e98c9a982ac9b8b741", display_name="Blog Posts", singular_name="Blog Post", slug="posts" + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.create( + site_id="580e63e98c9a982ac9b8b741", display_name="Blog Posts", singular_name="Blog Post", slug="posts" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "580e63fc8c9a982ac9b8b745", + "displayName": "Blog Posts", + "singularName": "Blog Post", + "slug": "post", + "createdOn": "2016-10-24T19:41:48Z", + "lastUpdated": "2016-10-24T19:42:38Z", + "fields": [ + { + "id": "23cc2d952d4e4631ffd4345d2743db4e", + "isRequired": True, + "isEditable": True, + "type": "PlainText", + "slug": "name", + "displayName": "Name", + "helpText": "helpText", + } + ], + } + expected_types: typing.Any = { + "id": None, + "displayName": None, + "singularName": None, + "slug": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + "fields": ( + "list", + { + 0: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + } + }, + ), + } + response = client.collections.get(collection_id="580e63fc8c9a982ac9b8b745") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.collections.get(collection_id="580e63fc8c9a982ac9b8b745") + validate_response(async_response, expected_response, expected_types) + + +async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.collections.delete(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.collections.delete(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + is None + ) diff --git a/tests/test_components.py b/tests/test_components.py new file mode 100644 index 0000000..2f5a42d --- /dev/null +++ b/tests/test_components.py @@ -0,0 +1,266 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response +from webflow import TextNodeWrite +from webflow import ComponentInstanceNodePropertyOverridesWrite +from webflow import ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem +from webflow.resources.components import ComponentPropertiesWritePropertiesItem + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "components": [ + { + "id": "6596da6045e56dee495bcbba", + "name": "Primary Button", + "group": "Buttons", + "description": "A default button component that can be used across the site", + "readonly": True, + }, + { + "id": "658205daa3e8206a523b5ad4", + "name": "Secondary Button", + "group": "Buttons", + "description": "A secondary button component that can be used across the site", + "readonly": True, + }, + { + "id": "6258612d1ee792848f805dcf", + "name": "Card", + "group": "Buttons", + "description": "A button component that can be used across the site", + "readonly": True, + }, + { + "id": "68a2b1d1ee792848f805dcf", + "name": "Nav", + "group": "Buttons", + "description": "A button component that can be used across the site", + "readonly": True, + }, + ], + "pagination": {"limit": 20, "offset": 0, "total": 4}, + } + expected_types: typing.Any = { + "components": ( + "list", + { + 0: {"id": None, "name": None, "group": None, "description": None, "readonly": None}, + 1: {"id": None, "name": None, "group": None, "description": None, "readonly": None}, + 2: {"id": None, "name": None, "group": None, "description": None, "readonly": None}, + 3: {"id": None, "name": None, "group": None, "description": None, "readonly": None}, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.components.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.components.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_get_content(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "componentId": "69118560-d0bc-15fc-bbf8-b8fe5f6535b5", + "nodes": [ + { + "type": "component-instance", + "id": "a245c12d-995b-55ee-5ec7-aa36a6cad623", + "componentId": "nodes", + "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + }, + { + "type": "component-instance", + "id": "a245c12d-995b-55ee-5ec7-aa36a6cad627", + "componentId": "nodes", + "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + }, + { + "type": "component-instance", + "id": "a245c12d-995b-55ee-5ec7-aa36a6cad629", + "componentId": "nodes", + "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + }, + { + "type": "component-instance", + "id": "a245c12d-995b-55ee-5ec7-aa36a6cad631", + "componentId": "6258612d1ee792848f805dcf", + "propertyOverrides": [ + { + "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad633", + "type": "Plain Text", + "text": {"text": "Don't Panic!"}, + }, + { + "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad635", + "type": "Rich Text", + "text": {"html": "

Always know where your towel is.

"}, + }, + ], + }, + ], + "pagination": {"limit": 4, "offset": 0, "total": 4}, + } + expected_types: typing.Any = { + "componentId": None, + "nodes": ("list", {0: "no_validate", 1: "no_validate", 2: "no_validate", 3: "no_validate"}), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.components.get_content( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.components.get_content( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_update_content(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = {"errors": ["errors"]} + expected_types: typing.Any = {"errors": ("list", {0: None})} + response = client.components.update_content( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + nodes=[ + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

" + ), + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + ComponentInstanceNodePropertyOverridesWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + property_overrides=[ + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", + text="

Time is an illusion

", + ), + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", text="Life, the Universe and Everything" + ), + ], + ), + ], + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.components.update_content( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + nodes=[ + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

" + ), + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + ComponentInstanceNodePropertyOverridesWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + property_overrides=[ + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", + text="

Time is an illusion

", + ), + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", text="Life, the Universe and Everything" + ), + ], + ), + ], + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get_properties(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "componentId": "658205daa3e8206a523b5ad4", + "properties": [ + { + "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad623", + "type": "Plain Text", + "label": "Title", + "text": {"text": "The Hitchhiker's Guide to the Galaxy"}, + }, + { + "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad627", + "type": "Rich Text", + "label": "Content", + "text": {"html": "

Don't Panic!

Always know where your towel is.

"}, + }, + ], + "pagination": {"limit": 2, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "componentId": None, + "properties": ( + "list", + { + 0: {"propertyId": None, "type": None, "label": None, "text": {"text": None}}, + 1: {"propertyId": None, "type": None, "label": None, "text": {"html": None}}, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.components.get_properties( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.components.get_properties( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_update_properties(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = {"errors": ["errors"]} + expected_types: typing.Any = {"errors": ("list", {0: None})} + response = client.components.update_properties( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + properties=[ + ComponentPropertiesWritePropertiesItem( + property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="The Hitchhiker’s Guide to the Galaxy" + ), + ComponentPropertiesWritePropertiesItem( + property_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Dont Panic!

Always know where your towel is.

", + ), + ], + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.components.update_properties( + site_id="580e63e98c9a982ac9b8b741", + component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", + locale_id="65427cf400e02b306eaa04a0", + properties=[ + ComponentPropertiesWritePropertiesItem( + property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="The Hitchhiker’s Guide to the Galaxy" + ), + ComponentPropertiesWritePropertiesItem( + property_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Dont Panic!

Always know where your towel is.

", + ), + ], + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_ecommerce.py b/tests/test_ecommerce.py new file mode 100644 index 0000000..b33a06f --- /dev/null +++ b/tests/test_ecommerce.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response + + +async def test_get_settings(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "siteId": "5eb0b5583bf24e2d3a488969", + "createdOn": "2018-10-04T15:21:02Z", + "defaultCurrency": "USD", + } + expected_types: typing.Any = {"siteId": None, "createdOn": "datetime", "defaultCurrency": None} + response = client.ecommerce.get_settings(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.ecommerce.get_settings(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_forms.py b/tests/test_forms.py new file mode 100644 index 0000000..ee88977 --- /dev/null +++ b/tests/test_forms.py @@ -0,0 +1,266 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "forms": [ + { + "displayName": "Email Form", + "createdOn": "2016-10-24T19:41:29Z", + "lastUpdated": "2016-10-24T19:43:17Z", + "fields": { + "0": {"displayName": "Email", "userVisible": True}, + "1": {"displayName": "Email", "userVisible": True}, + }, + "responseSettings": { + "redirectUrl": "https://example.com", + "redirectMethod": "GET", + "sendEmailConfirmation": True, + }, + "id": "589a331aa51e760df7ccb89e", + "siteId": "580e63e98c9a982ac9b8b741", + "siteDomainId": "6419db964a9c436a4baf6248", + "pageId": "6419db964a9c43f6a3af6348", + "pageName": "Home", + "formElementId": "4e038d2c-6a1e-4953-7be9-a59a2b453177", + "workspaceId": "580e63fc8c9a982ac9b8b744", + }, + { + "displayName": "Name Form", + "createdOn": "2016-10-24T19:41:29Z", + "lastUpdated": "2016-10-24T19:43:17Z", + "fields": {"0": {"displayName": "Email", "userVisible": True}}, + "responseSettings": { + "redirectUrl": "https://example.com", + "redirectMethod": "GET", + "sendEmailConfirmation": False, + }, + "id": "580ff8d7ba3e45ba9fe588e9", + "siteId": "580e63e98c9a982ac9b8b741", + "siteDomainId": "6419db964a9c436a4baf6248", + "pageId": "6419db964a9c43f6a3af6348", + "pageName": "Home", + "formElementId": "4e038d2c-6a1e-4953-7be9-a59a2b453177", + "workspaceId": "580e63fc8c9a982ac9b8b744", + }, + ], + "pagination": {"limit": 25, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "forms": ( + "list", + { + 0: { + "displayName": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + "fields": ( + "dict", + { + 0: (None, {"displayName": None, "userVisible": None}), + 1: (None, {"displayName": None, "userVisible": None}), + }, + ), + "responseSettings": {"redirectUrl": None, "redirectMethod": None, "sendEmailConfirmation": None}, + "id": None, + "siteId": None, + "siteDomainId": None, + "pageId": None, + "pageName": None, + "formElementId": None, + "workspaceId": None, + }, + 1: { + "displayName": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + "fields": ("dict", {0: (None, {"displayName": None, "userVisible": None})}), + "responseSettings": {"redirectUrl": None, "redirectMethod": None, "sendEmailConfirmation": None}, + "id": None, + "siteId": None, + "siteDomainId": None, + "pageId": None, + "pageName": None, + "formElementId": None, + "workspaceId": None, + }, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.forms.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.forms.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "displayName": "Email Form", + "createdOn": "2016-10-24T19:41:29Z", + "lastUpdated": "2016-10-24T19:43:17Z", + "fields": { + "660d5bcc9c0772150459dfb1": { + "displayName": "Name", + "type": "Plain", + "placeholder": "Enter your email", + "userVisible": True, + }, + "589a331aa51e760df7ccb89d": { + "displayName": "Email", + "type": "Email", + "placeholder": "Enter your email", + "userVisible": True, + }, + }, + "responseSettings": { + "redirectUrl": "https://example.com", + "redirectMethod": "GET", + "redirectAction": "POST https://example.com", + "sendEmailConfirmation": True, + }, + "id": "589a331aa51e760df7ccb89e", + "siteId": "580e63e98c9a982ac9b8b741", + "siteDomainId": "6419db964a9c436a4baf6248", + "pageId": "6419db964a9c43f6a3af6348", + "pageName": "Home", + "formElementId": "4e038d2c-6a1e-4953-7be9-a59a2b453177", + "workspaceId": "580e63fc8c9a982ac9b8b744", + } + expected_types: typing.Any = { + "displayName": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + "fields": ( + "dict", + { + 0: (None, {"displayName": None, "type": None, "placeholder": None, "userVisible": None}), + 1: (None, {"displayName": None, "type": None, "placeholder": None, "userVisible": None}), + }, + ), + "responseSettings": { + "redirectUrl": None, + "redirectMethod": None, + "redirectAction": None, + "sendEmailConfirmation": None, + }, + "id": None, + "siteId": None, + "siteDomainId": None, + "pageId": None, + "pageName": None, + "formElementId": None, + "workspaceId": None, + } + response = client.forms.get(form_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.forms.get(form_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_list_submissions(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "formSubmissions": [ + { + "id": "6321ca84df3949bfc6752327", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, + }, + { + "id": "660d64fabf6e0a0d4edab981", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Ford", "Last Name": "Prefect"}, + }, + ], + "pagination": {"limit": 25, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "formSubmissions": ( + "list", + { + 0: { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + }, + 1: { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + }, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.forms.list_submissions(form_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.forms.list_submissions(form_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_get_submission(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "6321ca84df3949bfc6752327", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, + } + expected_types: typing.Any = { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + } + response = client.forms.get_submission(form_submission_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.forms.get_submission(form_submission_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_update_submission(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "6321ca84df3949bfc6752327", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, + } + expected_types: typing.Any = { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + } + response = client.forms.update_submission(form_submission_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.forms.update_submission(form_submission_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_inventory.py b/tests/test_inventory.py new file mode 100644 index 0000000..a4f1518 --- /dev/null +++ b/tests/test_inventory.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = {"id": "5bfedb42bab0ad90fa7dad39", "quantity": 100, "inventoryType": "finite"} + expected_types: typing.Any = {"id": None, "quantity": None, "inventoryType": None} + response = client.inventory.list(collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.inventory.list( + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = {"id": "5bfedb42bab0ad90fa7dad39", "quantity": 100, "inventoryType": "finite"} + expected_types: typing.Any = {"id": None, "quantity": None, "inventoryType": None} + response = client.inventory.update( + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", inventory_type="infinite" + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.inventory.update( + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", inventory_type="infinite" + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_orders.py b/tests/test_orders.py new file mode 100644 index 0000000..a874784 --- /dev/null +++ b/tests/test_orders.py @@ -0,0 +1,2327 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "orders": [ + { + "orderId": "7c1-9fd", + "status": "unfulfilled", + "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", + "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', + "acceptedOn": "2024-04-10T13:16:21Z", + "fulfilledOn": "2018-12-03T22:06:15Z", + "refundedOn": "2018-12-03T22:06:15Z", + "disputedOn": "2018-12-03T22:06:15Z", + "disputeUpdatedOn": "2018-12-03T22:06:15Z", + "disputeLastStatus": "warning_needs_response", + "customerPaid": {"unit": "USD", "value": "5892", "string": " 211.55 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": " 200.89 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": " 4.23 USD"}, + "allAddresses": [ + { + "type": "billing", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + { + "type": "shipping", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + ], + "shippingAddress": { + "type": "shipping", + "japanType": "kanji", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "billingAddress": { + "type": "billing", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "shippingProvider": "Shipping Company, Co.", + "shippingTracking": "tr00000000002", + "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000002", + "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, + "purchasedItems": [ + { + "count": 2, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 111.22 USD"}, + "productId": "66072fb61b89448912e26791", + "productName": "Luxurious Fresh Ball", + "productSlug": "luxurious-fresh-ball", + "variantId": "66072fb71b89448912e2683f", + "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", + "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "weight": 11, + "width": 82, + "height": 70, + "length": 9, + }, + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 83.09 USD"}, + "productId": "66072fb61b89448912e2678b", + "productName": "Incredible Bronze Towels", + "productSlug": "incredible-bronze-towels", + "variantId": "66072fb71b89448912e2681e", + "variantName": "Incredible Bronze Towels Sleek: Frozen, Incredible: Metal", + "variantSlug": "incredible-bronze-towels-sleek-frozen-incredible-metal", + "variantSKU": "incredible-bronze-towels-sleek-frozen-incredible-metal", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 83.09 USD"}, + "width": 19, + "height": 72, + "length": 18, + }, + ], + "purchasedItemsCount": 3, + "stripeDetails": { + "paymentMethod": "pm_1P410gJYFi4lcbXWbeKghqjK", + "paymentIntentId": "pi_3P410iJYFi4lcbXW0EKKgcVg", + "customerId": "cus_Ptod8KJBiiPgnH", + "chargeId": "ch_3P410iJYFi4lcbXW0DxUkzCH", + }, + "stripeCard": { + "last4": "4242", + "brand": "Visa", + "ownerName": "Arthur Dent", + "expires": {"year": 2025, "month": 4}, + }, + "paypalDetails": { + "orderId": "1a2b3c4d5e6f7g8h9i0j", + "payerId": "9k8j7i6h5g4f3e2d1c0b", + "captureId": "qwe123rty456uio789p", + "refundId": "abcde12345fghij67890", + "refundReason": "Customer requested refund", + "disputeId": "zxcvbnm987poiuytrewq", + }, + "customData": [{"key": "value"}], + "metadata": {"isBuyNow": False}, + "isCustomerDeleted": False, + "isShippingRequired": False, + "hasDownloads": False, + "paymentProcessor": "stripe", + "totals": { + "extras": [ + { + "type": "tax", + "name": "State Taxes", + "description": "CA Taxes (6.25%)", + "price": {"unit": "USD", "value": "5892", "string": "3.44"}, + } + ] + }, + "downloadFiles": [ + { + "id": "5e9a5eba75e0ac242e1b6f64", + "name": "The modern web design process - Webflow Ebook.pdf", + "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", + } + ], + }, + { + "orderId": "fc7-128", + "status": "refunded", + "comment": "Example comment to myself", + "orderComment": "", + "acceptedOn": "2024-03-29T21:29:21Z", + "fulfilledOn": "2018-12-03T22:06:15Z", + "refundedOn": "2024-04-08T18:25:04Z", + "disputedOn": "2018-12-03T22:06:15Z", + "disputeUpdatedOn": "2018-12-03T22:06:15Z", + "disputeLastStatus": "warning_needs_response", + "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "allAddresses": [ + { + "type": "billing", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + { + "type": "shipping", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + ], + "shippingAddress": { + "type": "shipping", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "billingAddress": { + "type": "billing", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "shippingProvider": "Shipping Company, Co.", + "shippingTracking": "tr00000000001", + "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", + "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, + "purchasedItems": [ + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "productId": "66072fb61b89448912e26791", + "productName": "Luxurious Fresh Ball", + "productSlug": "luxurious-fresh-ball", + "variantId": "66072fb71b89448912e2683f", + "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", + "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "weight": 11, + "width": 82, + "height": 70, + "length": 9, + }, + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "productId": "66072fb61b89448912e26799", + "productName": "Recycled Steel Gloves", + "productSlug": "recycled-steel-gloves", + "variantId": "66072fb91b89448912e26ab9", + "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", + "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "weight": 38, + "width": 76, + "height": 85, + "length": 40, + }, + ], + "purchasedItemsCount": 2, + "stripeDetails": { + "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", + "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", + "customerId": "cus_PpRsNHwWdUoRKR", + "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", + "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", + "refundReason": "fraudulent", + }, + "stripeCard": { + "last4": "4242", + "brand": "Visa", + "ownerName": "Arthur Dent", + "expires": {"year": 2024, "month": 4}, + }, + "paypalDetails": { + "orderId": "1a2b3c4d5e6f7g8h9i0j", + "payerId": "9k8j7i6h5g4f3e2d1c0b", + "captureId": "qwe123rty456uio789p", + "refundId": "abcde12345fghij67890", + "refundReason": "Customer requested refund", + "disputeId": "zxcvbnm987poiuytrewq", + }, + "customData": [{"key": "value"}], + "metadata": {"isBuyNow": False}, + "isCustomerDeleted": False, + "isShippingRequired": True, + "hasDownloads": False, + "paymentProcessor": "stripe", + "totals": { + "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "extras": [ + { + "type": "tax", + "name": "State Taxes", + "description": "NY Taxes (4.00%)", + "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + }, + { + "type": "tax", + "name": "City Taxes", + "description": "NEW YORK Taxes (4.88%)", + "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + }, + { + "type": "shipping", + "name": "Flat", + "description": "", + "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + }, + ], + "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + }, + "downloadFiles": [ + { + "id": "5e9a5eba75e0ac242e1b6f64", + "name": "New product guide", + "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", + } + ], + }, + ], + "pagination": {"limit": 100, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "orders": ( + "list", + { + 0: { + "orderId": None, + "status": None, + "comment": None, + "orderComment": None, + "acceptedOn": "datetime", + "fulfilledOn": "datetime", + "refundedOn": "datetime", + "disputedOn": "datetime", + "disputeUpdatedOn": "datetime", + "disputeLastStatus": None, + "customerPaid": {"unit": None, "value": None, "string": None}, + "netAmount": {"unit": None, "value": None, "string": None}, + "applicationFee": {"unit": None, "value": None, "string": None}, + "allAddresses": ( + "list", + { + 0: { + "type": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + 1: { + "type": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + }, + ), + "shippingAddress": { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "billingAddress": { + "type": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "shippingProvider": None, + "shippingTracking": None, + "shippingTrackingURL": None, + "customerInfo": {"fullName": None, "email": None}, + "purchasedItems": ( + "list", + { + 0: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + 1: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "width": None, + "height": None, + "length": None, + }, + }, + ), + "purchasedItemsCount": None, + "stripeDetails": { + "paymentMethod": None, + "paymentIntentId": None, + "customerId": None, + "chargeId": None, + }, + "stripeCard": { + "last4": None, + "brand": None, + "ownerName": None, + "expires": {"year": None, "month": None}, + }, + "paypalDetails": { + "orderId": None, + "payerId": None, + "captureId": None, + "refundId": None, + "refundReason": None, + "disputeId": None, + }, + "customData": ("list", {0: ("dict", {0: (None, None)})}), + "metadata": {"isBuyNow": None}, + "isCustomerDeleted": None, + "isShippingRequired": None, + "hasDownloads": None, + "paymentProcessor": None, + "totals": { + "extras": ( + "list", + { + 0: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + } + }, + ) + }, + "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), + }, + 1: { + "orderId": None, + "status": None, + "comment": None, + "orderComment": None, + "acceptedOn": "datetime", + "fulfilledOn": "datetime", + "refundedOn": "datetime", + "disputedOn": "datetime", + "disputeUpdatedOn": "datetime", + "disputeLastStatus": None, + "customerPaid": {"unit": None, "value": None, "string": None}, + "netAmount": {"unit": None, "value": None, "string": None}, + "applicationFee": {"unit": None, "value": None, "string": None}, + "allAddresses": ( + "list", + { + 0: { + "type": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + 1: { + "type": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + }, + ), + "shippingAddress": { + "type": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "billingAddress": { + "type": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "shippingProvider": None, + "shippingTracking": None, + "shippingTrackingURL": None, + "customerInfo": {"fullName": None, "email": None}, + "purchasedItems": ( + "list", + { + 0: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + 1: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + }, + ), + "purchasedItemsCount": None, + "stripeDetails": { + "paymentMethod": None, + "paymentIntentId": None, + "customerId": None, + "chargeId": None, + "refundId": None, + "refundReason": None, + }, + "stripeCard": { + "last4": None, + "brand": None, + "ownerName": None, + "expires": {"year": None, "month": None}, + }, + "paypalDetails": { + "orderId": None, + "payerId": None, + "captureId": None, + "refundId": None, + "refundReason": None, + "disputeId": None, + }, + "customData": ("list", {0: ("dict", {0: (None, None)})}), + "metadata": {"isBuyNow": None}, + "isCustomerDeleted": None, + "isShippingRequired": None, + "hasDownloads": None, + "paymentProcessor": None, + "totals": { + "subtotal": {"unit": None, "value": None, "string": None}, + "extras": ( + "list", + { + 0: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 1: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 2: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + }, + ), + "total": {"unit": None, "value": None, "string": None}, + }, + "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), + }, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.orders.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.orders.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "orderId": "fc7-128", + "status": "refunded", + "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", + "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', + "acceptedOn": "2024-03-29T21:29:21Z", + "fulfilledOn": "2024-03-29T21:29:21Z", + "refundedOn": "2024-04-08T18:25:04Z", + "disputedOn": "2024-03-29T21:29:21Z", + "disputeUpdatedOn": "2024-03-29T21:29:21Z", + "disputeLastStatus": "charge_refunded", + "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "allAddresses": [ + { + "type": "billing", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + { + "type": "shipping", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + ], + "shippingAddress": { + "type": "shipping", + "japanType": "kanji", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "billingAddress": { + "type": "billing", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "shippingProvider": "Shipping Company, Co.", + "shippingTracking": "tr00000000001", + "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", + "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, + "purchasedItems": [ + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "productId": "66072fb61b89448912e26791", + "productName": "Luxurious Fresh Ball", + "productSlug": "luxurious-fresh-ball", + "variantId": "66072fb71b89448912e2683f", + "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", + "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "weight": 11, + "width": 82, + "height": 70, + "length": 9, + }, + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "productId": "66072fb61b89448912e26799", + "productName": "Recycled Steel Gloves", + "productSlug": "recycled-steel-gloves", + "variantId": "66072fb91b89448912e26ab9", + "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", + "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "weight": 38, + "width": 76, + "height": 85, + "length": 40, + }, + ], + "purchasedItemsCount": 2, + "stripeDetails": { + "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", + "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", + "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", + "customerId": "cus_PpRsNHwWdUoRKR", + "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", + "disputeId": "disputeId", + "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", + "refundReason": "fraudulent", + }, + "stripeCard": { + "last4": "4242", + "brand": "Visa", + "ownerName": "Arthur Dent", + "expires": {"year": 2024, "month": 4}, + }, + "paypalDetails": { + "orderId": "1a2b3c4d5e6f7g8h9i0j", + "payerId": "9k8j7i6h5g4f3e2d1c0b", + "captureId": "qwe123rty456uio789p", + "refundId": "abcde12345fghij67890", + "refundReason": "Customer requested refund", + "disputeId": "zxcvbnm987poiuytrewq", + }, + "customData": [{"key": "value"}], + "metadata": {"isBuyNow": False}, + "isCustomerDeleted": False, + "isShippingRequired": True, + "hasDownloads": False, + "paymentProcessor": "stripe", + "totals": { + "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "extras": [ + { + "type": "tax", + "name": "State Taxes", + "description": "NY Taxes (4.00%)", + "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + }, + { + "type": "tax", + "name": "City Taxes", + "description": "NEW YORK Taxes (4.88%)", + "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + }, + { + "type": "shipping", + "name": "Flat", + "description": "", + "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + }, + ], + "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + }, + "downloadFiles": [ + { + "id": "5e9a5eba75e0ac242e1b6f64", + "name": "New product guide", + "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", + } + ], + } + expected_types: typing.Any = { + "orderId": None, + "status": None, + "comment": None, + "orderComment": None, + "acceptedOn": "datetime", + "fulfilledOn": "datetime", + "refundedOn": "datetime", + "disputedOn": "datetime", + "disputeUpdatedOn": "datetime", + "disputeLastStatus": None, + "customerPaid": {"unit": None, "value": None, "string": None}, + "netAmount": {"unit": None, "value": None, "string": None}, + "applicationFee": {"unit": None, "value": None, "string": None}, + "allAddresses": ( + "list", + { + 0: { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + 1: { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + }, + ), + "shippingAddress": { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "billingAddress": { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "shippingProvider": None, + "shippingTracking": None, + "shippingTrackingURL": None, + "customerInfo": {"fullName": None, "email": None}, + "purchasedItems": ( + "list", + { + 0: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + 1: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + }, + ), + "purchasedItemsCount": None, + "stripeDetails": { + "subscriptionId": None, + "paymentMethod": None, + "paymentIntentId": None, + "customerId": None, + "chargeId": None, + "disputeId": None, + "refundId": None, + "refundReason": None, + }, + "stripeCard": {"last4": None, "brand": None, "ownerName": None, "expires": {"year": None, "month": None}}, + "paypalDetails": { + "orderId": None, + "payerId": None, + "captureId": None, + "refundId": None, + "refundReason": None, + "disputeId": None, + }, + "customData": ("list", {0: ("dict", {0: (None, None)})}), + "metadata": {"isBuyNow": None}, + "isCustomerDeleted": None, + "isShippingRequired": None, + "hasDownloads": None, + "paymentProcessor": None, + "totals": { + "subtotal": {"unit": None, "value": None, "string": None}, + "extras": ( + "list", + { + 0: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 1: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 2: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + }, + ), + "total": {"unit": None, "value": None, "string": None}, + }, + "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), + } + response = client.orders.get(site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.orders.get( + site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "orderId": "fc7-128", + "status": "refunded", + "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", + "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', + "acceptedOn": "2024-03-29T21:29:21Z", + "fulfilledOn": "2024-03-29T21:29:21Z", + "refundedOn": "2024-04-08T18:25:04Z", + "disputedOn": "2024-03-29T21:29:21Z", + "disputeUpdatedOn": "2024-03-29T21:29:21Z", + "disputeLastStatus": "charge_refunded", + "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "allAddresses": [ + { + "type": "billing", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + { + "type": "shipping", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + ], + "shippingAddress": { + "type": "shipping", + "japanType": "kanji", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "billingAddress": { + "type": "billing", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "shippingProvider": "Shipping Company, Co.", + "shippingTracking": "tr00000000001", + "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", + "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, + "purchasedItems": [ + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "productId": "66072fb61b89448912e26791", + "productName": "Luxurious Fresh Ball", + "productSlug": "luxurious-fresh-ball", + "variantId": "66072fb71b89448912e2683f", + "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", + "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "weight": 11, + "width": 82, + "height": 70, + "length": 9, + }, + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "productId": "66072fb61b89448912e26799", + "productName": "Recycled Steel Gloves", + "productSlug": "recycled-steel-gloves", + "variantId": "66072fb91b89448912e26ab9", + "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", + "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "weight": 38, + "width": 76, + "height": 85, + "length": 40, + }, + ], + "purchasedItemsCount": 2, + "stripeDetails": { + "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", + "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", + "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", + "customerId": "cus_PpRsNHwWdUoRKR", + "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", + "disputeId": "disputeId", + "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", + "refundReason": "fraudulent", + }, + "stripeCard": { + "last4": "4242", + "brand": "Visa", + "ownerName": "Arthur Dent", + "expires": {"year": 2024, "month": 4}, + }, + "paypalDetails": { + "orderId": "1a2b3c4d5e6f7g8h9i0j", + "payerId": "9k8j7i6h5g4f3e2d1c0b", + "captureId": "qwe123rty456uio789p", + "refundId": "abcde12345fghij67890", + "refundReason": "Customer requested refund", + "disputeId": "zxcvbnm987poiuytrewq", + }, + "customData": [{"key": "value"}], + "metadata": {"isBuyNow": False}, + "isCustomerDeleted": False, + "isShippingRequired": True, + "hasDownloads": False, + "paymentProcessor": "stripe", + "totals": { + "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "extras": [ + { + "type": "tax", + "name": "State Taxes", + "description": "NY Taxes (4.00%)", + "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + }, + { + "type": "tax", + "name": "City Taxes", + "description": "NEW YORK Taxes (4.88%)", + "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + }, + { + "type": "shipping", + "name": "Flat", + "description": "", + "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + }, + ], + "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + }, + "downloadFiles": [ + { + "id": "5e9a5eba75e0ac242e1b6f64", + "name": "New product guide", + "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", + } + ], + } + expected_types: typing.Any = { + "orderId": None, + "status": None, + "comment": None, + "orderComment": None, + "acceptedOn": "datetime", + "fulfilledOn": "datetime", + "refundedOn": "datetime", + "disputedOn": "datetime", + "disputeUpdatedOn": "datetime", + "disputeLastStatus": None, + "customerPaid": {"unit": None, "value": None, "string": None}, + "netAmount": {"unit": None, "value": None, "string": None}, + "applicationFee": {"unit": None, "value": None, "string": None}, + "allAddresses": ( + "list", + { + 0: { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + 1: { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + }, + ), + "shippingAddress": { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "billingAddress": { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "shippingProvider": None, + "shippingTracking": None, + "shippingTrackingURL": None, + "customerInfo": {"fullName": None, "email": None}, + "purchasedItems": ( + "list", + { + 0: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + 1: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + }, + ), + "purchasedItemsCount": None, + "stripeDetails": { + "subscriptionId": None, + "paymentMethod": None, + "paymentIntentId": None, + "customerId": None, + "chargeId": None, + "disputeId": None, + "refundId": None, + "refundReason": None, + }, + "stripeCard": {"last4": None, "brand": None, "ownerName": None, "expires": {"year": None, "month": None}}, + "paypalDetails": { + "orderId": None, + "payerId": None, + "captureId": None, + "refundId": None, + "refundReason": None, + "disputeId": None, + }, + "customData": ("list", {0: ("dict", {0: (None, None)})}), + "metadata": {"isBuyNow": None}, + "isCustomerDeleted": None, + "isShippingRequired": None, + "hasDownloads": None, + "paymentProcessor": None, + "totals": { + "subtotal": {"unit": None, "value": None, "string": None}, + "extras": ( + "list", + { + 0: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 1: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 2: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + }, + ), + "total": {"unit": None, "value": None, "string": None}, + }, + "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), + } + response = client.orders.update(site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.orders.update( + site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "orderId": "fc7-128", + "status": "refunded", + "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", + "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', + "acceptedOn": "2024-03-29T21:29:21Z", + "fulfilledOn": "2024-03-29T21:29:21Z", + "refundedOn": "2024-04-08T18:25:04Z", + "disputedOn": "2024-03-29T21:29:21Z", + "disputeUpdatedOn": "2024-03-29T21:29:21Z", + "disputeLastStatus": "charge_refunded", + "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "allAddresses": [ + { + "type": "billing", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + { + "type": "shipping", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + ], + "shippingAddress": { + "type": "shipping", + "japanType": "kanji", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "billingAddress": { + "type": "billing", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "shippingProvider": "Shipping Company, Co.", + "shippingTracking": "tr00000000001", + "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", + "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, + "purchasedItems": [ + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "productId": "66072fb61b89448912e26791", + "productName": "Luxurious Fresh Ball", + "productSlug": "luxurious-fresh-ball", + "variantId": "66072fb71b89448912e2683f", + "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", + "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "weight": 11, + "width": 82, + "height": 70, + "length": 9, + }, + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "productId": "66072fb61b89448912e26799", + "productName": "Recycled Steel Gloves", + "productSlug": "recycled-steel-gloves", + "variantId": "66072fb91b89448912e26ab9", + "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", + "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "weight": 38, + "width": 76, + "height": 85, + "length": 40, + }, + ], + "purchasedItemsCount": 2, + "stripeDetails": { + "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", + "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", + "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", + "customerId": "cus_PpRsNHwWdUoRKR", + "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", + "disputeId": "disputeId", + "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", + "refundReason": "fraudulent", + }, + "stripeCard": { + "last4": "4242", + "brand": "Visa", + "ownerName": "Arthur Dent", + "expires": {"year": 2024, "month": 4}, + }, + "paypalDetails": { + "orderId": "1a2b3c4d5e6f7g8h9i0j", + "payerId": "9k8j7i6h5g4f3e2d1c0b", + "captureId": "qwe123rty456uio789p", + "refundId": "abcde12345fghij67890", + "refundReason": "Customer requested refund", + "disputeId": "zxcvbnm987poiuytrewq", + }, + "customData": [{"key": "value"}], + "metadata": {"isBuyNow": False}, + "isCustomerDeleted": False, + "isShippingRequired": True, + "hasDownloads": False, + "paymentProcessor": "stripe", + "totals": { + "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "extras": [ + { + "type": "tax", + "name": "State Taxes", + "description": "NY Taxes (4.00%)", + "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + }, + { + "type": "tax", + "name": "City Taxes", + "description": "NEW YORK Taxes (4.88%)", + "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + }, + { + "type": "shipping", + "name": "Flat", + "description": "", + "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + }, + ], + "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + }, + "downloadFiles": [ + { + "id": "5e9a5eba75e0ac242e1b6f64", + "name": "New product guide", + "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", + } + ], + } + expected_types: typing.Any = { + "orderId": None, + "status": None, + "comment": None, + "orderComment": None, + "acceptedOn": "datetime", + "fulfilledOn": "datetime", + "refundedOn": "datetime", + "disputedOn": "datetime", + "disputeUpdatedOn": "datetime", + "disputeLastStatus": None, + "customerPaid": {"unit": None, "value": None, "string": None}, + "netAmount": {"unit": None, "value": None, "string": None}, + "applicationFee": {"unit": None, "value": None, "string": None}, + "allAddresses": ( + "list", + { + 0: { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + 1: { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + }, + ), + "shippingAddress": { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "billingAddress": { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "shippingProvider": None, + "shippingTracking": None, + "shippingTrackingURL": None, + "customerInfo": {"fullName": None, "email": None}, + "purchasedItems": ( + "list", + { + 0: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + 1: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + }, + ), + "purchasedItemsCount": None, + "stripeDetails": { + "subscriptionId": None, + "paymentMethod": None, + "paymentIntentId": None, + "customerId": None, + "chargeId": None, + "disputeId": None, + "refundId": None, + "refundReason": None, + }, + "stripeCard": {"last4": None, "brand": None, "ownerName": None, "expires": {"year": None, "month": None}}, + "paypalDetails": { + "orderId": None, + "payerId": None, + "captureId": None, + "refundId": None, + "refundReason": None, + "disputeId": None, + }, + "customData": ("list", {0: ("dict", {0: (None, None)})}), + "metadata": {"isBuyNow": None}, + "isCustomerDeleted": None, + "isShippingRequired": None, + "hasDownloads": None, + "paymentProcessor": None, + "totals": { + "subtotal": {"unit": None, "value": None, "string": None}, + "extras": ( + "list", + { + 0: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 1: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 2: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + }, + ), + "total": {"unit": None, "value": None, "string": None}, + }, + "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), + } + response = client.orders.update_fulfill(site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.orders.update_fulfill( + site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "orderId": "fc7-128", + "status": "refunded", + "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", + "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', + "acceptedOn": "2024-03-29T21:29:21Z", + "fulfilledOn": "2024-03-29T21:29:21Z", + "refundedOn": "2024-04-08T18:25:04Z", + "disputedOn": "2024-03-29T21:29:21Z", + "disputeUpdatedOn": "2024-03-29T21:29:21Z", + "disputeLastStatus": "charge_refunded", + "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "allAddresses": [ + { + "type": "billing", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + { + "type": "shipping", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + ], + "shippingAddress": { + "type": "shipping", + "japanType": "kanji", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "billingAddress": { + "type": "billing", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "shippingProvider": "Shipping Company, Co.", + "shippingTracking": "tr00000000001", + "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", + "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, + "purchasedItems": [ + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "productId": "66072fb61b89448912e26791", + "productName": "Luxurious Fresh Ball", + "productSlug": "luxurious-fresh-ball", + "variantId": "66072fb71b89448912e2683f", + "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", + "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "weight": 11, + "width": 82, + "height": 70, + "length": 9, + }, + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "productId": "66072fb61b89448912e26799", + "productName": "Recycled Steel Gloves", + "productSlug": "recycled-steel-gloves", + "variantId": "66072fb91b89448912e26ab9", + "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", + "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "weight": 38, + "width": 76, + "height": 85, + "length": 40, + }, + ], + "purchasedItemsCount": 2, + "stripeDetails": { + "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", + "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", + "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", + "customerId": "cus_PpRsNHwWdUoRKR", + "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", + "disputeId": "disputeId", + "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", + "refundReason": "fraudulent", + }, + "stripeCard": { + "last4": "4242", + "brand": "Visa", + "ownerName": "Arthur Dent", + "expires": {"year": 2024, "month": 4}, + }, + "paypalDetails": { + "orderId": "1a2b3c4d5e6f7g8h9i0j", + "payerId": "9k8j7i6h5g4f3e2d1c0b", + "captureId": "qwe123rty456uio789p", + "refundId": "abcde12345fghij67890", + "refundReason": "Customer requested refund", + "disputeId": "zxcvbnm987poiuytrewq", + }, + "customData": [{"key": "value"}], + "metadata": {"isBuyNow": False}, + "isCustomerDeleted": False, + "isShippingRequired": True, + "hasDownloads": False, + "paymentProcessor": "stripe", + "totals": { + "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "extras": [ + { + "type": "tax", + "name": "State Taxes", + "description": "NY Taxes (4.00%)", + "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + }, + { + "type": "tax", + "name": "City Taxes", + "description": "NEW YORK Taxes (4.88%)", + "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + }, + { + "type": "shipping", + "name": "Flat", + "description": "", + "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + }, + ], + "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + }, + "downloadFiles": [ + { + "id": "5e9a5eba75e0ac242e1b6f64", + "name": "New product guide", + "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", + } + ], + } + expected_types: typing.Any = { + "orderId": None, + "status": None, + "comment": None, + "orderComment": None, + "acceptedOn": "datetime", + "fulfilledOn": "datetime", + "refundedOn": "datetime", + "disputedOn": "datetime", + "disputeUpdatedOn": "datetime", + "disputeLastStatus": None, + "customerPaid": {"unit": None, "value": None, "string": None}, + "netAmount": {"unit": None, "value": None, "string": None}, + "applicationFee": {"unit": None, "value": None, "string": None}, + "allAddresses": ( + "list", + { + 0: { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + 1: { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + }, + ), + "shippingAddress": { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "billingAddress": { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "shippingProvider": None, + "shippingTracking": None, + "shippingTrackingURL": None, + "customerInfo": {"fullName": None, "email": None}, + "purchasedItems": ( + "list", + { + 0: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + 1: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + }, + ), + "purchasedItemsCount": None, + "stripeDetails": { + "subscriptionId": None, + "paymentMethod": None, + "paymentIntentId": None, + "customerId": None, + "chargeId": None, + "disputeId": None, + "refundId": None, + "refundReason": None, + }, + "stripeCard": {"last4": None, "brand": None, "ownerName": None, "expires": {"year": None, "month": None}}, + "paypalDetails": { + "orderId": None, + "payerId": None, + "captureId": None, + "refundId": None, + "refundReason": None, + "disputeId": None, + }, + "customData": ("list", {0: ("dict", {0: (None, None)})}), + "metadata": {"isBuyNow": None}, + "isCustomerDeleted": None, + "isShippingRequired": None, + "hasDownloads": None, + "paymentProcessor": None, + "totals": { + "subtotal": {"unit": None, "value": None, "string": None}, + "extras": ( + "list", + { + 0: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 1: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 2: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + }, + ), + "total": {"unit": None, "value": None, "string": None}, + }, + "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), + } + response = client.orders.update_unfulfill(site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.orders.update_unfulfill( + site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "orderId": "fc7-128", + "status": "refunded", + "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", + "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', + "acceptedOn": "2024-03-29T21:29:21Z", + "fulfilledOn": "2024-03-29T21:29:21Z", + "refundedOn": "2024-04-08T18:25:04Z", + "disputedOn": "2024-03-29T21:29:21Z", + "disputeUpdatedOn": "2024-03-29T21:29:21Z", + "disputeLastStatus": "charge_refunded", + "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "allAddresses": [ + { + "type": "billing", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + { + "type": "shipping", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + ], + "shippingAddress": { + "type": "shipping", + "japanType": "kanji", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "billingAddress": { + "type": "billing", + "japanType": "kana", + "addressee": "Arthur Dent", + "line1": "20 W 34th St", + "line2": "Empire State Building", + "city": "New York", + "state": "New York", + "country": "US", + "postalCode": "10118", + }, + "shippingProvider": "Shipping Company, Co.", + "shippingTracking": "tr00000000001", + "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", + "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, + "purchasedItems": [ + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "productId": "66072fb61b89448912e26791", + "productName": "Luxurious Fresh Ball", + "productSlug": "luxurious-fresh-ball", + "variantId": "66072fb71b89448912e2683f", + "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", + "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "weight": 11, + "width": 82, + "height": 70, + "length": 9, + }, + { + "count": 1, + "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "productId": "66072fb61b89448912e26799", + "productName": "Recycled Steel Gloves", + "productSlug": "recycled-steel-gloves", + "variantId": "66072fb91b89448912e26ab9", + "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", + "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", + "variantImage": { + "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + }, + "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "weight": 38, + "width": 76, + "height": 85, + "length": 40, + }, + ], + "purchasedItemsCount": 2, + "stripeDetails": { + "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", + "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", + "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", + "customerId": "cus_PpRsNHwWdUoRKR", + "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", + "disputeId": "disputeId", + "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", + "refundReason": "fraudulent", + }, + "stripeCard": { + "last4": "4242", + "brand": "Visa", + "ownerName": "Arthur Dent", + "expires": {"year": 2024, "month": 4}, + }, + "paypalDetails": { + "orderId": "1a2b3c4d5e6f7g8h9i0j", + "payerId": "9k8j7i6h5g4f3e2d1c0b", + "captureId": "qwe123rty456uio789p", + "refundId": "abcde12345fghij67890", + "refundReason": "Customer requested refund", + "disputeId": "zxcvbnm987poiuytrewq", + }, + "customData": [{"key": "value"}], + "metadata": {"isBuyNow": False}, + "isCustomerDeleted": False, + "isShippingRequired": True, + "hasDownloads": False, + "paymentProcessor": "stripe", + "totals": { + "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "extras": [ + { + "type": "tax", + "name": "State Taxes", + "description": "NY Taxes (4.00%)", + "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + }, + { + "type": "tax", + "name": "City Taxes", + "description": "NEW YORK Taxes (4.88%)", + "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + }, + { + "type": "shipping", + "name": "Flat", + "description": "", + "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + }, + ], + "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + }, + "downloadFiles": [ + { + "id": "5e9a5eba75e0ac242e1b6f64", + "name": "New product guide", + "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", + } + ], + } + expected_types: typing.Any = { + "orderId": None, + "status": None, + "comment": None, + "orderComment": None, + "acceptedOn": "datetime", + "fulfilledOn": "datetime", + "refundedOn": "datetime", + "disputedOn": "datetime", + "disputeUpdatedOn": "datetime", + "disputeLastStatus": None, + "customerPaid": {"unit": None, "value": None, "string": None}, + "netAmount": {"unit": None, "value": None, "string": None}, + "applicationFee": {"unit": None, "value": None, "string": None}, + "allAddresses": ( + "list", + { + 0: { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + 1: { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + }, + ), + "shippingAddress": { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "billingAddress": { + "type": None, + "japanType": None, + "addressee": None, + "line1": None, + "line2": None, + "city": None, + "state": None, + "country": None, + "postalCode": None, + }, + "shippingProvider": None, + "shippingTracking": None, + "shippingTrackingURL": None, + "customerInfo": {"fullName": None, "email": None}, + "purchasedItems": ( + "list", + { + 0: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + 1: { + "count": None, + "rowTotal": {"unit": None, "value": None, "string": None}, + "productId": None, + "productName": None, + "productSlug": None, + "variantId": None, + "variantName": None, + "variantSlug": None, + "variantSKU": None, + "variantImage": {"url": None}, + "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, + "width": None, + "height": None, + "length": None, + }, + }, + ), + "purchasedItemsCount": None, + "stripeDetails": { + "subscriptionId": None, + "paymentMethod": None, + "paymentIntentId": None, + "customerId": None, + "chargeId": None, + "disputeId": None, + "refundId": None, + "refundReason": None, + }, + "stripeCard": {"last4": None, "brand": None, "ownerName": None, "expires": {"year": None, "month": None}}, + "paypalDetails": { + "orderId": None, + "payerId": None, + "captureId": None, + "refundId": None, + "refundReason": None, + "disputeId": None, + }, + "customData": ("list", {0: ("dict", {0: (None, None)})}), + "metadata": {"isBuyNow": None}, + "isCustomerDeleted": None, + "isShippingRequired": None, + "hasDownloads": None, + "paymentProcessor": None, + "totals": { + "subtotal": {"unit": None, "value": None, "string": None}, + "extras": ( + "list", + { + 0: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 1: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + 2: { + "type": None, + "name": None, + "description": None, + "price": {"unit": None, "value": None, "string": None}, + }, + }, + ), + "total": {"unit": None, "value": None, "string": None}, + }, + "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), + } + response = client.orders.refund(site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.orders.refund( + site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415" + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_pages.py b/tests/test_pages.py new file mode 100644 index 0000000..716c201 --- /dev/null +++ b/tests/test_pages.py @@ -0,0 +1,403 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response +import datetime +from webflow import PageSeo +from webflow import PageOpenGraph +from webflow import TextNodeWrite +from webflow import ComponentInstanceNodePropertyOverridesWrite +from webflow import ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "pages": [ + { + "id": "6596da6045e56dee495bcbba", + "siteId": "6258612d1ee792848f805dcf", + "title": "Guide to the Galaxy", + "slug": "guide-to-the-galaxy", + "parentId": "6419db964a9c435aa3af6251", + "collectionId": "6390c49774a71f12831a08e3", + "createdOn": "2024-03-11T10:42:00Z", + "lastUpdated": "2024-03-11T10:42:42Z", + "archived": False, + "draft": False, + "canBranch": True, + "isBranch": False, + "isMembersOnly": False, + "seo": { + "title": "The Ultimate Hitchhiker's Guide to the Galaxy", + "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", + }, + "openGraph": { + "title": "Explore the Cosmos with The Ultimate Guide", + "titleCopied": False, + "description": "Dive deep into the mysteries of the universe with your guide to everything galactic.", + "descriptionCopied": False, + }, + "localeId": "653fd9af6a07fc9cfd7a5e57", + "publishedPath": "/en-us/guide-to-the-galaxy", + }, + { + "id": "6596da6045e56dee495bcbad", + "siteId": "6258612d1ee792848f805dcf", + "title": "Towel Day Celebrations", + "slug": "towel-day", + "parentId": "6419db964a9c435aa3af6251", + "collectionId": "6390c49774a71f12831a08e3", + "createdOn": "2024-05-25T09:00:00Z", + "lastUpdated": "2024-05-25T09:42:00Z", + "archived": False, + "draft": False, + "canBranch": True, + "isBranch": False, + "isMembersOnly": False, + "seo": { + "title": "Celebrate Towel Day - The Hitchhiker's Guide to the Galaxy", + "description": "A guide to celebrating Towel Day, in honor of the most massively useful thing an interstellar hitchhiker can have.", + }, + "openGraph": { + "title": "Towel Day - Don't Panic", + "titleCopied": False, + "description": "Join the galaxy in celebrating Towel Day, the day dedicated to carrying towels everywhere in memory of Douglas Adams.", + "descriptionCopied": False, + }, + "localeId": "653fd9af6a07fc9cfd7a5e57", + "publishedPath": "/en-us/towel-day", + }, + ], + "pagination": {"limit": 20, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "pages": ( + "list", + { + 0: { + "id": None, + "siteId": None, + "title": None, + "slug": None, + "parentId": None, + "collectionId": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + "archived": None, + "draft": None, + "canBranch": None, + "isBranch": None, + "isMembersOnly": None, + "seo": {"title": None, "description": None}, + "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, + "localeId": None, + "publishedPath": None, + }, + 1: { + "id": None, + "siteId": None, + "title": None, + "slug": None, + "parentId": None, + "collectionId": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + "archived": None, + "draft": None, + "canBranch": None, + "isBranch": None, + "isMembersOnly": None, + "seo": {"title": None, "description": None}, + "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, + "localeId": None, + "publishedPath": None, + }, + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.pages.list(site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.pages.list( + site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get_metadata(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "6596da6045e56dee495bcbba", + "siteId": "6258612d1ee792848f805dcf", + "title": "Guide to the Galaxy", + "slug": "guide-to-the-galaxy", + "parentId": "6419db964a9c435aa3af6251", + "collectionId": "6390c49774a71f12831a08e3", + "createdOn": "2024-03-11T10:42:00Z", + "lastUpdated": "2024-03-11T10:42:42Z", + "archived": False, + "draft": False, + "canBranch": True, + "isBranch": False, + "isMembersOnly": False, + "seo": { + "title": "The Ultimate Hitchhiker's Guide to the Galaxy", + "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", + }, + "openGraph": { + "title": "Explore the Cosmos with The Ultimate Guide", + "titleCopied": False, + "description": "Dive deep into the mysteries of the universe with your guide to everything galactic.", + "descriptionCopied": False, + }, + "localeId": "653fd9af6a07fc9cfd7a5e57", + "publishedPath": "/en-us/guide-to-the-galaxy", + } + expected_types: typing.Any = { + "id": None, + "siteId": None, + "title": None, + "slug": None, + "parentId": None, + "collectionId": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + "archived": None, + "draft": None, + "canBranch": None, + "isBranch": None, + "isMembersOnly": None, + "seo": {"title": None, "description": None}, + "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, + "localeId": None, + "publishedPath": None, + } + response = client.pages.get_metadata(page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.pages.get_metadata( + page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_update_page_settings(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "6596da6045e56dee495bcbba", + "siteId": "6258612d1ee792848f805dcf", + "title": "Guide to the Galaxy", + "slug": "guide-to-the-galaxy", + "parentId": "6419db964a9c435aa3af6251", + "collectionId": "6390c49774a71f12831a08e3", + "createdOn": "2024-03-11T10:42:00Z", + "lastUpdated": "2024-03-11T10:42:42Z", + "archived": False, + "draft": False, + "canBranch": True, + "isBranch": False, + "isMembersOnly": False, + "seo": { + "title": "The Ultimate Hitchhiker's Guide to the Galaxy", + "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", + }, + "openGraph": { + "title": "Explore the Cosmos with The Ultimate Guide", + "titleCopied": False, + "description": "Dive deep into the mysteries of the universe with your guide to everything galactic.", + "descriptionCopied": False, + }, + "localeId": "653fd9af6a07fc9cfd7a5e57", + "publishedPath": "/en-us/guide-to-the-galaxy", + } + expected_types: typing.Any = { + "id": None, + "siteId": None, + "title": None, + "slug": None, + "parentId": None, + "collectionId": None, + "createdOn": "datetime", + "lastUpdated": "datetime", + "archived": None, + "draft": None, + "canBranch": None, + "isBranch": None, + "isMembersOnly": None, + "seo": {"title": None, "description": None}, + "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, + "localeId": None, + "publishedPath": None, + } + response = client.pages.update_page_settings( + page_id="63c720f9347c2139b248e552", + locale_id="65427cf400e02b306eaa04a0", + id="6596da6045e56dee495bcbba", + site_id="6258612d1ee792848f805dcf", + title="Guide to the Galaxy", + slug="guide-to-the-galaxy", + created_on=datetime.datetime.fromisoformat("2024-03-11 10:42:00+00:00"), + last_updated=datetime.datetime.fromisoformat("2024-03-11 10:42:42+00:00"), + archived=False, + draft=False, + can_branch=True, + is_branch=False, + seo=PageSeo( + title="The Ultimate Hitchhiker's Guide to the Galaxy", + description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", + ), + open_graph=PageOpenGraph( + title="Explore the Cosmos with The Ultimate Guide", + title_copied=False, + description="Dive deep into the mysteries of the universe with your guide to everything galactic.", + description_copied=False, + ), + page_locale_id="653fd9af6a07fc9cfd7a5e57", + published_path="/en-us/guide-to-the-galaxy", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.pages.update_page_settings( + page_id="63c720f9347c2139b248e552", + locale_id="65427cf400e02b306eaa04a0", + id="6596da6045e56dee495bcbba", + site_id="6258612d1ee792848f805dcf", + title="Guide to the Galaxy", + slug="guide-to-the-galaxy", + created_on=datetime.datetime.fromisoformat("2024-03-11 10:42:00+00:00"), + last_updated=datetime.datetime.fromisoformat("2024-03-11 10:42:42+00:00"), + archived=False, + draft=False, + can_branch=True, + is_branch=False, + seo=PageSeo( + title="The Ultimate Hitchhiker's Guide to the Galaxy", + description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", + ), + open_graph=PageOpenGraph( + title="Explore the Cosmos with The Ultimate Guide", + title_copied=False, + description="Dive deep into the mysteries of the universe with your guide to everything galactic.", + description_copied=False, + ), + page_locale_id="653fd9af6a07fc9cfd7a5e57", + published_path="/en-us/guide-to-the-galaxy", + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get_content(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "pageId": "658205daa3e8206a523b5ad4", + "nodes": [ + { + "type": "component-instance", + "id": "a245c12d-995b-55ee-5ec7-aa36a6cad623", + "componentId": "nodes", + "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + }, + { + "type": "component-instance", + "id": "a245c12d-995b-55ee-5ec7-aa36a6cad627", + "componentId": "nodes", + "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + }, + { + "type": "component-instance", + "id": "a245c12d-995b-55ee-5ec7-aa36a6cad629", + "componentId": "nodes", + "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + }, + { + "type": "component-instance", + "id": "a245c12d-995b-55ee-5ec7-aa36a6cad631", + "componentId": "6258612d1ee792848f805dcf", + "propertyOverrides": [ + { + "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad633", + "type": "Plain Text", + "label": "Catchphrase", + "text": {"text": "Don't Panic!"}, + }, + { + "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad635", + "type": "Rich Text", + "label": "Tagline", + "text": {"html": "

Always know where your towel is.

"}, + }, + ], + }, + ], + "pagination": {"limit": 4, "offset": 0, "total": 4}, + } + expected_types: typing.Any = { + "pageId": None, + "nodes": ("list", {0: "no_validate", 1: "no_validate", 2: "no_validate", 3: "no_validate"}), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.pages.get_content(page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.pages.get_content( + page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_update_static_content(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = {"errors": ["errors"]} + expected_types: typing.Any = {"errors": ("list", {0: None})} + response = client.pages.update_static_content( + page_id="63c720f9347c2139b248e552", + locale_id="localeId", + nodes=[ + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

" + ), + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + ComponentInstanceNodePropertyOverridesWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + property_overrides=[ + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", + text="

Time is an illusion

", + ), + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", text="Life, the Universe and Everything" + ), + ], + ), + ], + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.pages.update_static_content( + page_id="63c720f9347c2139b248e552", + locale_id="localeId", + nodes=[ + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

" + ), + TextNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", + text="

Don't Panic!

Always know where your towel is.

", + ), + ComponentInstanceNodePropertyOverridesWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", + property_overrides=[ + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", + text="

Time is an illusion

", + ), + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( + property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", text="Life, the Universe and Everything" + ), + ], + ), + ], + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_products.py b/tests/test_products.py new file mode 100644 index 0000000..03d28db --- /dev/null +++ b/tests/test_products.py @@ -0,0 +1,465 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response +from webflow import Sku + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "items": [ + { + "product": { + "id": "660eb7a486d1d6e0412292d7", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2024-04-04T14:24:19Z", + "lastUpdated": "2024-04-04T14:30:19Z", + "createdOn": "2024-04-04T14:22:28Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "T-Shirt", + "slug": "t-shirt", + "description": "A plain cotton t-shirt.", + "shippable": True, + "sku-properties": [ + { + "id": "Color", + "name": "Color", + "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}], + } + ], + }, + }, + "skus": [ + { + "id": "580e63fc8c9a982ac9b8b745", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2023-03-17T18:47:35Z", + "lastUpdated": "2023-03-17T18:47:35Z", + "createdOn": "2023-03-17T18:47:35Z", + "fieldData": { + "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, + "name": "Blue T-shirt", + "slug": "t-shirt-blue", + "price": {"value": 100, "unit": "USD"}, + "quantity": 10, + }, + } + ], + } + ], + "pagination": {"limit": 100, "offset": 0, "total": 100}, + } + expected_types: typing.Any = { + "items": ( + "list", + { + 0: { + "product": { + "id": None, + "cmsLocaleId": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "createdOn": "datetime", + "isArchived": None, + "isDraft": None, + "fieldData": { + "name": None, + "slug": None, + "description": None, + "shippable": None, + "sku-properties": ( + "list", + { + 0: { + "id": None, + "name": None, + "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), + } + }, + ), + }, + }, + "skus": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "createdOn": "datetime", + "fieldData": { + "sku-values": ("dict", {0: (None, None)}), + "name": None, + "slug": None, + "price": {"value": None, "unit": None}, + "quantity": None, + }, + } + }, + ), + } + }, + ), + "pagination": {"limit": None, "offset": None, "total": None}, + } + response = client.products.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.products.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "product": { + "id": "660eb7a486d1d6e0412292d7", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2024-04-04T14:24:19Z", + "lastUpdated": "2024-04-04T14:30:19Z", + "createdOn": "2024-04-04T14:22:28Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "T-Shirt", + "slug": "t-shirt", + "description": "A plain cotton t-shirt.", + "shippable": True, + "sku-properties": [ + {"id": "Color", "name": "Color", "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}]} + ], + "categories": ["categories"], + "tax-category": "standard-taxable", + "default-sku": "default-sku", + "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", + }, + }, + "skus": [ + { + "id": "580e63fc8c9a982ac9b8b745", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2023-03-17T18:47:35Z", + "lastUpdated": "2023-03-17T18:47:35Z", + "createdOn": "2023-03-17T18:47:35Z", + "fieldData": { + "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, + "name": "Blue T-shirt", + "slug": "t-shirt-blue", + "price": {"value": 100, "unit": "USD"}, + "quantity": 10, + }, + } + ], + } + expected_types: typing.Any = { + "product": { + "id": None, + "cmsLocaleId": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "createdOn": "datetime", + "isArchived": None, + "isDraft": None, + "fieldData": { + "name": None, + "slug": None, + "description": None, + "shippable": None, + "sku-properties": ( + "list", + {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, + ), + "categories": ("list", {0: None}), + "tax-category": None, + "default-sku": None, + "ec-product-type": None, + }, + }, + "skus": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "createdOn": "datetime", + "fieldData": { + "sku-values": ("dict", {0: (None, None)}), + "name": None, + "slug": None, + "price": {"value": None, "unit": None}, + "quantity": None, + }, + } + }, + ), + } + response = client.products.create(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.products.create(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "product": { + "id": "660eb7a486d1d6e0412292d7", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2024-04-04T14:24:19Z", + "lastUpdated": "2024-04-04T14:30:19Z", + "createdOn": "2024-04-04T14:22:28Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "T-Shirt", + "slug": "t-shirt", + "description": "A plain cotton t-shirt.", + "shippable": True, + "sku-properties": [ + {"id": "Color", "name": "Color", "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}]} + ], + "categories": ["categories"], + "tax-category": "standard-taxable", + "default-sku": "default-sku", + "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", + }, + }, + "skus": [ + { + "id": "580e63fc8c9a982ac9b8b745", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2023-03-17T18:47:35Z", + "lastUpdated": "2023-03-17T18:47:35Z", + "createdOn": "2023-03-17T18:47:35Z", + "fieldData": { + "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, + "name": "Blue T-shirt", + "slug": "t-shirt-blue", + "price": {"value": 100, "unit": "USD"}, + "quantity": 10, + }, + } + ], + } + expected_types: typing.Any = { + "product": { + "id": None, + "cmsLocaleId": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "createdOn": "datetime", + "isArchived": None, + "isDraft": None, + "fieldData": { + "name": None, + "slug": None, + "description": None, + "shippable": None, + "sku-properties": ( + "list", + {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, + ), + "categories": ("list", {0: None}), + "tax-category": None, + "default-sku": None, + "ec-product-type": None, + }, + }, + "skus": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "createdOn": "datetime", + "fieldData": { + "sku-values": ("dict", {0: (None, None)}), + "name": None, + "slug": None, + "price": {"value": None, "unit": None}, + "quantity": None, + }, + } + }, + ), + } + response = client.products.get(site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.products.get( + site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "660eb7a486d1d6e0412292d7", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2024-04-04T14:24:19Z", + "lastUpdated": "2024-04-04T14:30:19Z", + "createdOn": "2024-04-04T14:22:28Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "T-Shirt", + "slug": "t-shirt", + "description": "A plain cotton t-shirt.", + "shippable": True, + "sku-properties": [ + {"id": "Color", "name": "Color", "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}]} + ], + "categories": ["categories"], + "tax-category": "standard-taxable", + "default-sku": "default-sku", + "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", + }, + } + expected_types: typing.Any = { + "id": None, + "cmsLocaleId": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "createdOn": "datetime", + "isArchived": None, + "isDraft": None, + "fieldData": { + "name": None, + "slug": None, + "description": None, + "shippable": None, + "sku-properties": ( + "list", + {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, + ), + "categories": ("list", {0: None}), + "tax-category": None, + "default-sku": None, + "ec-product-type": None, + }, + } + response = client.products.update(site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.products.update( + site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_create_sku(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "skus": [ + { + "id": "580e63fc8c9a982ac9b8b745", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2023-03-17T18:47:35Z", + "lastUpdated": "2023-03-17T18:47:35Z", + "createdOn": "2023-03-17T18:47:35Z", + "fieldData": { + "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, + "name": "Blue T-shirt", + "slug": "t-shirt-blue", + "price": {"value": 100, "unit": "USD"}, + "quantity": 10, + }, + } + ] + } + expected_types: typing.Any = { + "skus": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "createdOn": "datetime", + "fieldData": { + "sku-values": ("dict", {0: (None, None)}), + "name": None, + "slug": None, + "price": {"value": None, "unit": None}, + "quantity": None, + }, + } + }, + ) + } + response = client.products.create_sku( + site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", skus=[Sku()] + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.products.create_sku( + site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", skus=[Sku()] + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_update_sku(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "580e63fc8c9a982ac9b8b745", + "cmsLocaleId": "653ad57de882f528b32e810e", + "lastPublished": "2023-03-17T18:47:35Z", + "lastUpdated": "2023-03-17T18:47:35Z", + "createdOn": "2023-03-17T18:47:35Z", + "fieldData": { + "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, + "name": "Blue T-shirt", + "slug": "t-shirt-blue", + "price": {"value": 100, "unit": "USD"}, + "compare-at-price": {"value": 100, "unit": "USD"}, + "ec-sku-billing-method": "one-time", + "ec-sku-subscription-plan": {"interval": "day", "frequency": 1, "trial": 7, "plans": [{}]}, + "track-inventory": True, + "quantity": 10, + }, + } + expected_types: typing.Any = { + "id": None, + "cmsLocaleId": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "createdOn": "datetime", + "fieldData": { + "sku-values": ("dict", {0: (None, None)}), + "name": None, + "slug": None, + "price": {"value": None, "unit": None}, + "compare-at-price": {"value": None, "unit": None}, + "ec-sku-billing-method": None, + "ec-sku-subscription-plan": { + "interval": None, + "frequency": None, + "trial": None, + "plans": ("list", {0: {}}), + }, + "track-inventory": None, + "quantity": None, + }, + } + response = client.products.update_sku( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + sku_id="5e8518516e147040726cc415", + sku=Sku(), + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.products.update_sku( + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + sku_id="5e8518516e147040726cc415", + sku=Sku(), + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_scripts.py b/tests/test_scripts.py new file mode 100644 index 0000000..6432530 --- /dev/null +++ b/tests/test_scripts.py @@ -0,0 +1,157 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "registeredScripts": [ + { + "id": "alert", + "canCopy": False, + "displayName": "Alert", + "hostedLocation": "https://cdn.webflow.io/.../alert-0.0.1.js", + "integrityHash": "integrityHash", + "createdOn": "2022-10-26T00:28:54.191Z", + "lastUpdated": "lastUpdated", + "version": "0.0.1", + }, + { + "id": "alert", + "canCopy": False, + "displayName": "Alert", + "hostedLocation": "https://cdn.webflow.io/.../alert-0.0.2.js", + "integrityHash": "integrityHash", + "createdOn": "2022-10-26T00:28:54.191Z", + "lastUpdated": "lastUpdated", + "version": "0.0.2", + }, + { + "id": "cms_slider", + "canCopy": True, + "displayName": "CMS Slider", + "hostedLocation": "https://cdn.jsdelivr.net/.../cms_slider.js", + "integrityHash": "sha384-J+YlJ8v0gpaRoKH7SbFbEmxOZlAxLiwNjfSsBhDooGa5roXlPPpXbEevck4J7YZ+", + "createdOn": "2022-10-26T00:28:54.191Z", + "lastUpdated": "lastUpdated", + "version": "1.0.0", + }, + ] + } + expected_types: typing.Any = { + "registeredScripts": ( + "list", + { + 0: { + "id": None, + "canCopy": None, + "displayName": None, + "hostedLocation": None, + "integrityHash": None, + "createdOn": None, + "lastUpdated": None, + "version": None, + }, + 1: { + "id": None, + "canCopy": None, + "displayName": None, + "hostedLocation": None, + "integrityHash": None, + "createdOn": None, + "lastUpdated": None, + "version": None, + }, + 2: { + "id": None, + "canCopy": None, + "displayName": None, + "hostedLocation": None, + "integrityHash": None, + "createdOn": None, + "lastUpdated": None, + "version": None, + }, + }, + ) + } + response = client.scripts.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.scripts.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_register_hosted(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "cms_slider", + "canCopy": True, + "displayName": "CMS Slider", + "hostedLocation": "https://cdn.jsdelivr.net/.../cmsslider.js", + "integrityHash": "sha384-J+YlJ8v0gpaRoKH7SbFbEmxOZlAxLiwNjfSsBhDooGa5roXlPPpXbEevck4J7YZ+", + "createdOn": "2022-10-26T00:28:54.191Z", + "lastUpdated": "lastUpdated", + "version": "1.0.0", + } + expected_types: typing.Any = { + "id": None, + "canCopy": None, + "displayName": None, + "hostedLocation": None, + "integrityHash": None, + "createdOn": None, + "lastUpdated": None, + "version": None, + } + response = client.scripts.register_hosted( + site_id="580e63e98c9a982ac9b8b741", + hosted_location="hostedLocation", + integrity_hash="integrityHash", + version="version", + display_name="displayName", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.scripts.register_hosted( + site_id="580e63e98c9a982ac9b8b741", + hosted_location="hostedLocation", + integrity_hash="integrityHash", + version="version", + display_name="displayName", + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_register_inline(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "alert", + "canCopy": False, + "displayName": "Alert", + "hostedLocation": "https://uploads-ssl.webflow.com/6258612d1ee792848f805dcf%2F64b6c769ff52ba6c3d904a91%2F660d6e15b3d1696f2d2b1447%2Falert-0.0.1.js", + "integrityHash": "integrityHash", + "createdOn": "2022-10-26T00:28:54.191Z", + "lastUpdated": "lastUpdated", + "version": "0.0.1", + } + expected_types: typing.Any = { + "id": None, + "canCopy": None, + "displayName": None, + "hostedLocation": None, + "integrityHash": None, + "createdOn": None, + "lastUpdated": None, + "version": None, + } + response = client.scripts.register_inline( + site_id="580e63e98c9a982ac9b8b741", source_code="alert('hello world');", version="0.0.1", display_name="Alert" + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.scripts.register_inline( + site_id="580e63e98c9a982ac9b8b741", source_code="alert('hello world');", version="0.0.1", display_name="Alert" + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_sites.py b/tests/test_sites.py new file mode 100644 index 0000000..6e9dd9b --- /dev/null +++ b/tests/test_sites.py @@ -0,0 +1,637 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response + + +async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "670ecf86817e3cc7a510eb6a", + "workspaceId": "625860a7a6c16d624927122f", + "createdOn": "2024-10-15T20:24:38Z", + "displayName": "The Hitchiker‘s Guide", + "shortName": "hitchikers-guide", + "lastPublished": "2016-10-24T19:43:17Z", + "lastUpdated": "2024-10-15T20:24:38Z", + "previewUrl": "https://d1otoma47x30pg.cloudfront.net/580e63e98c9a982ac9b8b741/201610241243.png", + "timeZone": "America/Los_Angeles", + "parentFolderId": "670ece123598db72d9648be1", + "customDomains": [ + {"id": "589a331aa51e760df7ccb89d", "url": "test-api-domain.com", "lastPublished": "2022-12-07T16:51:37Z"} + ], + "locales": { + "primary": { + "id": "653fd9af6a07fc9cfd7a5e57", + "cmsLocaleId": "653ad57de882f528b32e810e", + "enabled": False, + "displayName": "English (United States)", + "displayImageId": "displayImageId", + "redirect": True, + "subdirectory": "", + "tag": "en-US", + }, + "secondary": [ + { + "id": "653fd9af6a07fc9cfd7a5e57", + "cmsLocaleId": "653ad57de882f528b32e810e", + "enabled": False, + "displayName": "English (United States)", + "redirect": True, + "subdirectory": "", + "tag": "en-US", + } + ], + }, + "dataCollectionEnabled": False, + "dataCollectionType": "always", + } + expected_types: typing.Any = { + "id": None, + "workspaceId": None, + "createdOn": "datetime", + "displayName": None, + "shortName": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "previewUrl": None, + "timeZone": None, + "parentFolderId": None, + "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), + "locales": { + "primary": { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "displayImageId": None, + "redirect": None, + "subdirectory": None, + "tag": None, + }, + "secondary": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "redirect": None, + "subdirectory": None, + "tag": None, + } + }, + ), + }, + "dataCollectionEnabled": None, + "dataCollectionType": None, + } + response = client.sites.create(workspace_id="580e63e98c9a982ac9b8b741", name="The Hitchhiker's Guide to the Galaxy") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.create( + workspace_id="580e63e98c9a982ac9b8b741", name="The Hitchhiker's Guide to the Galaxy" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "sites": [ + { + "id": "42e63e98c9a982ac9b8b741", + "workspaceId": "42e63fc8c9a982ac9b8b744", + "createdOn": "1979-10-12T12:00:00Z", + "displayName": "Heart of Gold Spaceship", + "shortName": "heart-of-gold", + "lastPublished": "2023-04-02T12:42:00Z", + "lastUpdated": "2016-10-24T19:43:17Z", + "previewUrl": "https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b741/197910121200.png", + "timeZone": "DeepSpace/InfiniteImprobability", + "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", + "customDomains": [ + { + "id": "589a331aa51e760df7ccb89e", + "url": "heartofgold.galaxy", + "lastPublished": "2022-12-07T16:51:37Z", + } + ], + "locales": { + "primary": { + "id": "653fd9af6a07fc9cfd7a5e57", + "cmsLocaleId": "653ad57de882f528b32e810e", + "enabled": True, + "displayName": "English - Heart of Gold Standard", + "redirect": False, + "subdirectory": "/en", + "tag": "The Ultimate Answer", + }, + "secondary": [ + { + "id": "653fd9af6a07fc9cfd7a5e58", + "cmsLocaleId": "653ad57de882f528b32e810g", + "enabled": True, + "displayName": "Betelgeusian - Vogon Liaison", + "redirect": True, + "subdirectory": "/bet", + "tag": "Vogon", + }, + { + "id": "653fd9af6a07fc9cfd7a5e59", + "cmsLocaleId": "653ad57de882f528b32e810h", + "enabled": False, + "displayName": "Magrathean - Custom Planet Designs", + "redirect": True, + "subdirectory": "/mg", + "tag": "Magrathean", + }, + ], + }, + "dataCollectionEnabled": True, + "dataCollectionType": "always", + }, + { + "id": "42e63e98c9a982ac9b8b742", + "workspaceId": "42e63fc8c9a982ac9b8b745", + "createdOn": "1981-10-12T12:00:00Z", + "displayName": "Marvin's Personal Blog", + "shortName": "paranoid-android", + "lastPublished": "2023-04-02T12:45:00Z", + "lastUpdated": "2016-10-24T19:43:17Z", + "previewUrl": "https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b742/198110121200.png", + "timeZone": "DeepSpace/Depression", + "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", + "customDomains": [ + {"id": "589a331aa51e760df7ccb89f", "url": "marvin.blog", "lastPublished": "2022-12-07T16:51:37Z"} + ], + "locales": { + "primary": { + "id": "653fd9af6a07fc9cfd7a5e57", + "cmsLocaleId": "653ad57de882f528b32e810e", + "enabled": True, + "displayName": "English - Marvin's Musings", + "redirect": False, + "subdirectory": "/en", + "tag": "English", + }, + "secondary": [ + { + "id": "653fd9af6a07fc9cfd7a5e56", + "cmsLocaleId": "653ad57de882f528b32e810f", + "enabled": True, + "displayName": "Squornshellous - Mattress Speak", + "redirect": True, + "subdirectory": "/sr", + "tag": "Squornshellous", + } + ], + }, + "dataCollectionEnabled": True, + "dataCollectionType": "always", + }, + { + "id": "42e63e98c9a982ac9b8b743", + "workspaceId": "42e63fc8c9a982ac9b8b746", + "createdOn": "1982-10-12T12:00:00Z", + "displayName": "Vogon Poetry Archive", + "shortName": "vogon-poetry", + "lastPublished": "2023-04-02T12:50:00Z", + "lastUpdated": "2016-10-24T19:43:17Z", + "previewUrl": "https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b743/198210121200.png", + "timeZone": "Vogsphere/PoetryHall", + "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", + "customDomains": [ + { + "id": "589a331aa51e760df7ccb8a0", + "url": "vogonpoetry.galaxy", + "lastPublished": "2022-12-07T16:51:37Z", + } + ], + "locales": { + "primary": { + "id": "653fd9af6a07fc9cfd7a5e55", + "cmsLocaleId": "653ad57de882f528b32e810d", + "enabled": True, + "displayName": "English - Vogon Verse", + "redirect": False, + "subdirectory": "/en", + "tag": "Third Worst Poetry", + }, + "secondary": [ + { + "id": "653fd9af6a07fc9cfd7a5e54", + "cmsLocaleId": "653ad57de882f528b32e810c", + "enabled": True, + "displayName": "Galactic - Universal Language", + "redirect": True, + "subdirectory": "/gl", + "tag": "Pan-Galactic Gargle Blaster", + } + ], + }, + "dataCollectionEnabled": True, + "dataCollectionType": "always", + }, + ] + } + expected_types: typing.Any = { + "sites": ( + "list", + { + 0: { + "id": None, + "workspaceId": None, + "createdOn": "datetime", + "displayName": None, + "shortName": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "previewUrl": None, + "timeZone": None, + "parentFolderId": None, + "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), + "locales": { + "primary": { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "redirect": None, + "subdirectory": None, + "tag": None, + }, + "secondary": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "redirect": None, + "subdirectory": None, + "tag": None, + }, + 1: { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "redirect": None, + "subdirectory": None, + "tag": None, + }, + }, + ), + }, + "dataCollectionEnabled": None, + "dataCollectionType": None, + }, + 1: { + "id": None, + "workspaceId": None, + "createdOn": "datetime", + "displayName": None, + "shortName": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "previewUrl": None, + "timeZone": None, + "parentFolderId": None, + "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), + "locales": { + "primary": { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "redirect": None, + "subdirectory": None, + "tag": None, + }, + "secondary": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "redirect": None, + "subdirectory": None, + "tag": None, + } + }, + ), + }, + "dataCollectionEnabled": None, + "dataCollectionType": None, + }, + 2: { + "id": None, + "workspaceId": None, + "createdOn": "datetime", + "displayName": None, + "shortName": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "previewUrl": None, + "timeZone": None, + "parentFolderId": None, + "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), + "locales": { + "primary": { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "redirect": None, + "subdirectory": None, + "tag": None, + }, + "secondary": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "redirect": None, + "subdirectory": None, + "tag": None, + } + }, + ), + }, + "dataCollectionEnabled": None, + "dataCollectionType": None, + }, + }, + ) + } + response = client.sites.list() + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.list() + validate_response(async_response, expected_response, expected_types) + + +async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "42e98c9a982ac9b8b742", + "workspaceId": "42e63e98c9a982ac9b8b742", + "createdOn": "1979-10-12T12:00:00Z", + "displayName": "The Hitchhiker's Guide to the Galaxy", + "shortName": "hitchhikers-guide", + "lastPublished": "2023-04-02T12:42:00Z", + "lastUpdated": "2023-04-02T12:42:00Z", + "previewUrl": "https://screenshots.webflow.com/sites/6258612d1ee792848f805dcf/20231219211811_d5990556c743f33b7071300a03bf67e6.png", + "timeZone": "Magrathea/FactoryFloor", + "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", + "customDomains": [ + { + "id": "589a331aa51e760df7ccb89d", + "url": "hitchhikersguide.galaxy", + "lastPublished": "2022-12-07T16:51:37Z", + }, + {"id": "589a331aa51e760df7ccb89e", "url": "heartofgold.spaceship", "lastPublished": "2022-12-07T16:51:37Z"}, + ], + "locales": { + "primary": { + "id": "653fd9af6a07fc9cfd7a5e57", + "cmsLocaleId": "653ad57de882f528b32e810e", + "enabled": False, + "displayName": "English (United States)", + "displayImageId": "displayImageId", + "redirect": True, + "subdirectory": "", + "tag": "en-US", + }, + "secondary": [ + { + "id": "653fd9af6a07fc9cfd7a5e57", + "cmsLocaleId": "653ad57de882f528b32e810e", + "enabled": False, + "displayName": "English (United States)", + "redirect": True, + "subdirectory": "", + "tag": "en-US", + } + ], + }, + "dataCollectionEnabled": True, + "dataCollectionType": "always", + } + expected_types: typing.Any = { + "id": None, + "workspaceId": None, + "createdOn": "datetime", + "displayName": None, + "shortName": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "previewUrl": None, + "timeZone": None, + "parentFolderId": None, + "customDomains": ( + "list", + { + 0: {"id": None, "url": None, "lastPublished": "datetime"}, + 1: {"id": None, "url": None, "lastPublished": "datetime"}, + }, + ), + "locales": { + "primary": { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "displayImageId": None, + "redirect": None, + "subdirectory": None, + "tag": None, + }, + "secondary": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "redirect": None, + "subdirectory": None, + "tag": None, + } + }, + ), + }, + "dataCollectionEnabled": None, + "dataCollectionType": None, + } + response = client.sites.get(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.get(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.sites.delete(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.sites.delete(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + +async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "42e98c9a982ac9b8b742", + "workspaceId": "42e63e98c9a982ac9b8b742", + "createdOn": "1979-10-12T12:00:00Z", + "displayName": "The Hitchhiker's Guide to the Galaxy", + "shortName": "hitchhikers-guide", + "lastPublished": "2023-04-02T12:42:00Z", + "lastUpdated": "2023-04-02T12:42:00Z", + "previewUrl": "https://screenshots.webflow.com/sites/6258612d1ee792848f805dcf/20231219211811_d5990556c743f33b7071300a03bf67e6.png", + "timeZone": "Magrathea/FactoryFloor", + "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", + "customDomains": [ + { + "id": "589a331aa51e760df7ccb89d", + "url": "hitchhikersguide.galaxy", + "lastPublished": "2022-12-07T16:51:37Z", + }, + {"id": "589a331aa51e760df7ccb89e", "url": "heartofgold.spaceship", "lastPublished": "2022-12-07T16:51:37Z"}, + ], + "locales": { + "primary": { + "id": "653fd9af6a07fc9cfd7a5e57", + "cmsLocaleId": "653ad57de882f528b32e810e", + "enabled": False, + "displayName": "English (United States)", + "displayImageId": "displayImageId", + "redirect": True, + "subdirectory": "", + "tag": "en-US", + }, + "secondary": [ + { + "id": "653fd9af6a07fc9cfd7a5e57", + "cmsLocaleId": "653ad57de882f528b32e810e", + "enabled": False, + "displayName": "English (United States)", + "redirect": True, + "subdirectory": "", + "tag": "en-US", + } + ], + }, + "dataCollectionEnabled": True, + "dataCollectionType": "always", + } + expected_types: typing.Any = { + "id": None, + "workspaceId": None, + "createdOn": "datetime", + "displayName": None, + "shortName": None, + "lastPublished": "datetime", + "lastUpdated": "datetime", + "previewUrl": None, + "timeZone": None, + "parentFolderId": None, + "customDomains": ( + "list", + { + 0: {"id": None, "url": None, "lastPublished": "datetime"}, + 1: {"id": None, "url": None, "lastPublished": "datetime"}, + }, + ), + "locales": { + "primary": { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "displayImageId": None, + "redirect": None, + "subdirectory": None, + "tag": None, + }, + "secondary": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "enabled": None, + "displayName": None, + "redirect": None, + "subdirectory": None, + "tag": None, + } + }, + ), + }, + "dataCollectionEnabled": None, + "dataCollectionType": None, + } + response = client.sites.update(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.update(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_get_custom_domain(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "customDomains": [ + { + "id": "589a331aa51e760df7ccb89d", + "url": "hitchhikersguide.galaxy", + "lastPublished": "2022-12-07T16:51:37Z", + }, + {"id": "589a331aa51e760df7ccb89e", "url": "heartofgold.spaceship", "lastPublished": "2022-12-07T16:51:37Z"}, + ] + } + expected_types: typing.Any = { + "customDomains": ( + "list", + { + 0: {"id": None, "url": None, "lastPublished": "datetime"}, + 1: {"id": None, "url": None, "lastPublished": "datetime"}, + }, + ) + } + response = client.sites.get_custom_domain(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.get_custom_domain(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_publish(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "customDomains": [ + {"id": "589a331aa51e760df7ccb89d", "url": "test-api-domain.com", "lastPublished": "2022-12-07T16:51:37Z"} + ], + "publishToWebflowSubdomain": True, + } + expected_types: typing.Any = { + "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), + "publishToWebflowSubdomain": None, + } + response = client.sites.publish(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.publish(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_token.py b/tests/test_token.py new file mode 100644 index 0000000..d57ee3b --- /dev/null +++ b/tests/test_token.py @@ -0,0 +1,66 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response + + +async def test_authorized_by(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "545bbecb7bdd6769632504a7", + "email": "some@email.com", + "firstName": "Some", + "lastName": "One", + } + expected_types: typing.Any = {"id": None, "email": None, "firstName": None, "lastName": None} + response = client.token.authorized_by() + validate_response(response, expected_response, expected_types) + + async_response = await async_client.token.authorized_by() + validate_response(async_response, expected_response, expected_types) + + +async def test_introspect(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "authorization": { + "id": "55818d58616600637b9a5786", + "createdOn": "2016-10-03T23:12:00Z", + "lastUsed": "2016-10-10T21:41:12Z", + "grantType": "authorization_code", + "rateLimit": 60, + "scope": "assets:read,assets:write", + "authorizedTo": { + "siteIds": ["62f3b1f7eafac55d0c64ef91"], + "workspaceIds": ["52f3b1f7eafac55d0c64ef91"], + "userIds": ["545bbecb7bdd6769632504a7"], + }, + }, + "application": { + "id": "55131cd036c09f7d07883dfc", + "description": "My Amazing App", + "homepage": "https://webflow.com", + "displayName": "My Amazing App", + }, + } + expected_types: typing.Any = { + "authorization": { + "id": None, + "createdOn": "datetime", + "lastUsed": "datetime", + "grantType": None, + "rateLimit": "integer", + "scope": None, + "authorizedTo": { + "siteIds": ("list", {0: None}), + "workspaceIds": ("list", {0: None}), + "userIds": ("list", {0: None}), + }, + }, + "application": None, + } + response = client.token.introspect() + validate_response(response, expected_response, expected_types) + + async_response = await async_client.token.introspect() + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_users.py b/tests/test_users.py new file mode 100644 index 0000000..abcbfd6 --- /dev/null +++ b/tests/test_users.py @@ -0,0 +1,301 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response +from webflow.resources.users import UsersUpdateRequestData + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "count": 5, + "limit": 5, + "offset": 0, + "total": 201, + "users": [ + { + "id": "6287ec36a841b25637c663df", + "isEmailVerified": False, + "lastUpdated": "2022-05-20T13:46:12Z", + "invitedOn": "2016-10-24T19:41:29Z", + "createdOn": "2022-05-20T13:46:12Z", + "lastLogin": "2016-10-24T19:41:29Z", + "status": "unverified", + "accessGroups": [{"slug": "vogon-construction-crew", "type": "admin"}], + }, + { + "id": "6287ec36a841b25637c663f0", + "isEmailVerified": False, + "lastUpdated": "2022-05-19T05:32:04Z", + "invitedOn": "2016-10-24T19:41:29Z", + "createdOn": "2022-05-19T05:32:04Z", + "lastLogin": "2016-10-24T19:41:29Z", + "status": "unverified", + "accessGroups": [{"slug": "improbability-drive-test-subjects", "type": "admin"}], + }, + { + "id": "6287ec36a841b25637c663d9", + "isEmailVerified": True, + "lastUpdated": "2022-05-17T03:34:06Z", + "invitedOn": "2016-10-24T19:41:29Z", + "createdOn": "2022-05-17T03:34:06Z", + "lastLogin": "2016-10-24T19:41:29Z", + "status": "verified", + "accessGroups": [{"slug": "heart-of-gold-crew", "type": "admin"}], + }, + { + "id": "6287ec37a841b25637c6641b", + "isEmailVerified": False, + "lastUpdated": "2022-05-15T03:46:09Z", + "invitedOn": "2016-10-24T19:41:29Z", + "createdOn": "2022-05-15T03:46:09Z", + "lastLogin": "2016-10-24T19:41:29Z", + "status": "unverified", + "accessGroups": [{"slug": "hitchhikers-guide-research-team", "type": "admin"}], + }, + { + "id": "6287ec37a841b25637c66449", + "isEmailVerified": True, + "lastUpdated": "2022-05-15T02:55:38Z", + "invitedOn": "2016-10-24T19:41:29Z", + "createdOn": "2022-05-15T02:55:38Z", + "lastLogin": "2016-10-24T19:41:29Z", + "status": "verified", + "accessGroups": [{"slug": "milliways-reservationists", "type": "admin"}], + }, + ], + } + expected_types: typing.Any = { + "count": None, + "limit": None, + "offset": None, + "total": None, + "users": ( + "list", + { + 0: { + "id": None, + "isEmailVerified": None, + "lastUpdated": "datetime", + "invitedOn": "datetime", + "createdOn": "datetime", + "lastLogin": "datetime", + "status": None, + "accessGroups": ("list", {0: {"slug": None, "type": None}}), + }, + 1: { + "id": None, + "isEmailVerified": None, + "lastUpdated": "datetime", + "invitedOn": "datetime", + "createdOn": "datetime", + "lastLogin": "datetime", + "status": None, + "accessGroups": ("list", {0: {"slug": None, "type": None}}), + }, + 2: { + "id": None, + "isEmailVerified": None, + "lastUpdated": "datetime", + "invitedOn": "datetime", + "createdOn": "datetime", + "lastLogin": "datetime", + "status": None, + "accessGroups": ("list", {0: {"slug": None, "type": None}}), + }, + 3: { + "id": None, + "isEmailVerified": None, + "lastUpdated": "datetime", + "invitedOn": "datetime", + "createdOn": "datetime", + "lastLogin": "datetime", + "status": None, + "accessGroups": ("list", {0: {"slug": None, "type": None}}), + }, + 4: { + "id": None, + "isEmailVerified": None, + "lastUpdated": "datetime", + "invitedOn": "datetime", + "createdOn": "datetime", + "lastLogin": "datetime", + "status": None, + "accessGroups": ("list", {0: {"slug": None, "type": None}}), + }, + }, + ), + } + response = client.users.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.users.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "6287ec36a841b25637c663df", + "isEmailVerified": True, + "lastUpdated": "2022-05-20T13:46:12Z", + "invitedOn": "2022-05-20T13:46:12Z", + "createdOn": "2022-05-20T13:46:12Z", + "lastLogin": "2022-05-20T13:46:12Z", + "status": "verified", + "accessGroups": [{"slug": "webflowers", "type": "admin"}], + "data": { + "data": { + "name": "name", + "email": "email", + "accept-privacy": True, + "accept-communications": True, + "additionalProperties": "additionalProperties", + } + }, + } + expected_types: typing.Any = { + "id": None, + "isEmailVerified": None, + "lastUpdated": "datetime", + "invitedOn": "datetime", + "createdOn": "datetime", + "lastLogin": "datetime", + "status": None, + "accessGroups": ("list", {0: {"slug": None, "type": None}}), + "data": { + "data": { + "name": None, + "email": None, + "accept-privacy": None, + "accept-communications": None, + "additionalProperties": None, + } + }, + } + response = client.users.get(site_id="580e63e98c9a982ac9b8b741", user_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.users.get( + site_id="580e63e98c9a982ac9b8b741", user_id="580e63e98c9a982ac9b8b741" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.users.delete(site_id="580e63e98c9a982ac9b8b741", user_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.users.delete(site_id="580e63e98c9a982ac9b8b741", user_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + +async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "6287ec36a841b25637c663df", + "isEmailVerified": True, + "lastUpdated": "2022-05-20T13:46:12Z", + "invitedOn": "2022-05-20T13:46:12Z", + "createdOn": "2022-05-20T13:46:12Z", + "lastLogin": "2022-05-20T13:46:12Z", + "status": "verified", + "accessGroups": [{"slug": "webflowers", "type": "admin"}], + "data": { + "data": { + "name": "name", + "email": "email", + "accept-privacy": True, + "accept-communications": True, + "additionalProperties": "additionalProperties", + } + }, + } + expected_types: typing.Any = { + "id": None, + "isEmailVerified": None, + "lastUpdated": "datetime", + "invitedOn": "datetime", + "createdOn": "datetime", + "lastLogin": "datetime", + "status": None, + "accessGroups": ("list", {0: {"slug": None, "type": None}}), + "data": { + "data": { + "name": None, + "email": None, + "accept-privacy": None, + "accept-communications": None, + "additionalProperties": None, + } + }, + } + response = client.users.update( + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", + data=UsersUpdateRequestData(name="Some One", accept_privacy=False, accept_communications=False), + access_groups=["webflowers", "platinum", "free-tier"], + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.users.update( + site_id="580e63e98c9a982ac9b8b741", + user_id="580e63e98c9a982ac9b8b741", + data=UsersUpdateRequestData(name="Some One", accept_privacy=False, accept_communications=False), + access_groups=["webflowers", "platinum", "free-tier"], + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_invite(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "6287ec36a841b25637c663df", + "isEmailVerified": True, + "lastUpdated": "2022-05-20T13:46:12Z", + "invitedOn": "2022-05-20T13:46:12Z", + "createdOn": "2022-05-20T13:46:12Z", + "lastLogin": "2022-05-20T13:46:12Z", + "status": "verified", + "accessGroups": [{"slug": "webflowers", "type": "admin"}], + "data": { + "data": { + "name": "name", + "email": "email", + "accept-privacy": True, + "accept-communications": True, + "additionalProperties": "additionalProperties", + } + }, + } + expected_types: typing.Any = { + "id": None, + "isEmailVerified": None, + "lastUpdated": "datetime", + "invitedOn": "datetime", + "createdOn": "datetime", + "lastLogin": "datetime", + "status": None, + "accessGroups": ("list", {0: {"slug": None, "type": None}}), + "data": { + "data": { + "name": None, + "email": None, + "accept-privacy": None, + "accept-communications": None, + "additionalProperties": None, + } + }, + } + response = client.users.invite( + site_id="580e63e98c9a982ac9b8b741", email="some.one@home.com", access_groups=["webflowers"] + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.users.invite( + site_id="580e63e98c9a982ac9b8b741", email="some.one@home.com", access_groups=["webflowers"] + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py new file mode 100644 index 0000000..4c19188 --- /dev/null +++ b/tests/test_webhooks.py @@ -0,0 +1,175 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from .utilities import validate_response +import datetime + + +async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "pagination": {"limit": 100, "offset": 0, "total": 100}, + "webhooks": [ + { + "id": "57ca0a9e418c504a6e1acbb6", + "triggerType": "form_submission", + "url": "https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", + "workspaceId": "4f4e46fd476ea8c507000001", + "siteId": "562ac0395358780a1f5e6fbd", + "filter": {"name": "Email Form"}, + "lastTriggered": "2023-02-08T23:59:28Z", + "createdOn": "2016-09-02T23:26:22Z", + }, + { + "id": "578d85cce0c47cd2865f4cf2", + "triggerType": "form_submission", + "url": "https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", + "workspaceId": "4f4e46fd476ea8c507000001", + "siteId": "562ac0395358780a1f5e6fbd", + "filter": {"name": "Email Form"}, + "lastTriggered": "2023-02-08T23:59:28Z", + "createdOn": "2016-07-19T01:43:40Z", + }, + { + "id": "578d85cce0c47cd2865f4cf3", + "triggerType": "form_submission", + "url": "https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", + "workspaceId": "4f4e46fd476ea8c507000001", + "siteId": "562ac0395358780a1f5e6fbd", + "filter": {"name": "Email Form"}, + "lastTriggered": "2023-02-08T23:59:28Z", + "createdOn": "2016-07-19T01:43:40Z", + }, + ], + } + expected_types: typing.Any = { + "pagination": {"limit": None, "offset": None, "total": None}, + "webhooks": ( + "list", + { + 0: { + "id": None, + "triggerType": None, + "url": None, + "workspaceId": None, + "siteId": None, + "filter": {"name": None}, + "lastTriggered": "datetime", + "createdOn": "datetime", + }, + 1: { + "id": None, + "triggerType": None, + "url": None, + "workspaceId": None, + "siteId": None, + "filter": {"name": None}, + "lastTriggered": "datetime", + "createdOn": "datetime", + }, + 2: { + "id": None, + "triggerType": None, + "url": None, + "workspaceId": None, + "siteId": None, + "filter": {"name": None}, + "lastTriggered": "datetime", + "createdOn": "datetime", + }, + }, + ), + } + response = client.webhooks.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.webhooks.list(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "582266e0cd48de0f0e3c6d8b", + "triggerType": "form_submission", + "url": "https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", + "workspaceId": "4f4e46fd476ea8c507000001", + "siteId": "562ac0395358780a1f5e6fbd", + "filter": {"name": "My Form"}, + "lastTriggered": "2023-02-08T23:59:28Z", + "createdOn": "2022-11-08T23:59:28Z", + } + expected_types: typing.Any = { + "id": None, + "triggerType": None, + "url": None, + "workspaceId": None, + "siteId": None, + "filter": {"name": None}, + "lastTriggered": "datetime", + "createdOn": "datetime", + } + response = client.webhooks.create( + site_id_="580e63e98c9a982ac9b8b741", + id="582266e0cd48de0f0e3c6d8b", + trigger_type="form_submission", + url="https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", + workspace_id="4f4e46fd476ea8c507000001", + site_id="562ac0395358780a1f5e6fbd", + last_triggered=datetime.datetime.fromisoformat("2023-02-08 23:59:28+00:00"), + created_on=datetime.datetime.fromisoformat("2022-11-08 23:59:28+00:00"), + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.webhooks.create( + site_id_="580e63e98c9a982ac9b8b741", + id="582266e0cd48de0f0e3c6d8b", + trigger_type="form_submission", + url="https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", + workspace_id="4f4e46fd476ea8c507000001", + site_id="562ac0395358780a1f5e6fbd", + last_triggered=datetime.datetime.fromisoformat("2023-02-08 23:59:28+00:00"), + created_on=datetime.datetime.fromisoformat("2022-11-08 23:59:28+00:00"), + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "582266e0cd48de0f0e3c6d8b", + "triggerType": "form_submission", + "url": "https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", + "workspaceId": "4f4e46fd476ea8c507000001", + "siteId": "562ac0395358780a1f5e6fbd", + "filter": {"name": "My Form"}, + "lastTriggered": "2023-02-08T23:59:28Z", + "createdOn": "2022-11-08T23:59:28Z", + } + expected_types: typing.Any = { + "id": None, + "triggerType": None, + "url": None, + "workspaceId": None, + "siteId": None, + "filter": {"name": None}, + "lastTriggered": "datetime", + "createdOn": "datetime", + } + response = client.webhooks.get(webhook_id="580e64008c9a982ac9b8b754") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.webhooks.get(webhook_id="580e64008c9a982ac9b8b754") + validate_response(async_response, expected_response, expected_types) + + +async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.webhooks.delete(webhook_id="580e64008c9a982ac9b8b754") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.webhooks.delete(webhook_id="580e64008c9a982ac9b8b754") # type: ignore[func-returns-value] + is None + ) diff --git a/tests/utilities.py b/tests/utilities.py new file mode 100644 index 0000000..3d22880 --- /dev/null +++ b/tests/utilities.py @@ -0,0 +1,162 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +import uuid + +from dateutil import parser + +import pydantic + + +def cast_field(json_expectation: typing.Any, type_expectation: typing.Any) -> typing.Any: + # Cast these specific types which come through as string and expect our + # models to cast to the correct type. + if type_expectation == "uuid": + return uuid.UUID(json_expectation) + elif type_expectation == "date": + return parser.parse(json_expectation).date() + elif type_expectation == "datetime": + return parser.parse(json_expectation) + elif type_expectation == "set": + return set(json_expectation) + elif type_expectation == "integer": + # Necessary as we allow numeric keys, but JSON makes them strings + return int(json_expectation) + + return json_expectation + + +def validate_field(response: typing.Any, json_expectation: typing.Any, type_expectation: typing.Any) -> None: + # Allow for an escape hatch if the object cannot be validated + if type_expectation == "no_validate": + return + + is_container_of_complex_type = False + # Parse types in containers, note that dicts are handled within `validate_response` + if isinstance(json_expectation, list): + if isinstance(type_expectation, tuple): + container_expectation = type_expectation[0] + contents_expectation = type_expectation[1] + + cast_json_expectation = [] + for idx, ex in enumerate(json_expectation): + if isinstance(contents_expectation, dict): + entry_expectation = contents_expectation.get(idx) + if isinstance(entry_expectation, dict): + is_container_of_complex_type = True + validate_response( + response=response[idx], + json_expectation=ex, + type_expectations=entry_expectation, + ) + else: + cast_json_expectation.append(cast_field(ex, entry_expectation)) + else: + cast_json_expectation.append(ex) + json_expectation = cast_json_expectation + + # Note that we explicitly do not allow for sets of pydantic models as they are not hashable, so + # if any of the values of the set have a type_expectation of a dict, we're assuming it's a pydantic + # model and keeping it a list. + if container_expectation != "set" or not any( + map( + lambda value: isinstance(value, dict), + list(contents_expectation.values()), + ) + ): + json_expectation = cast_field(json_expectation, container_expectation) + elif isinstance(type_expectation, tuple): + container_expectation = type_expectation[0] + contents_expectation = type_expectation[1] + if isinstance(contents_expectation, dict): + json_expectation = { + cast_field( + key, + contents_expectation.get(idx)[0] # type: ignore + if contents_expectation.get(idx) is not None + else None, + ): cast_field( + value, + contents_expectation.get(idx)[1] # type: ignore + if contents_expectation.get(idx) is not None + else None, + ) + for idx, (key, value) in enumerate(json_expectation.items()) + } + else: + json_expectation = cast_field(json_expectation, container_expectation) + elif type_expectation is not None: + json_expectation = cast_field(json_expectation, type_expectation) + + # When dealing with containers of models, etc. we're validating them implicitly, so no need to check the resultant list + if not is_container_of_complex_type: + assert ( + json_expectation == response + ), "Primitives found, expected: {0} (type: {1}), Actual: {2} (type: {3})".format( + json_expectation, type(json_expectation), response, type(response) + ) + + +# Arg type_expectations is a deeply nested structure that matches the response, but with the values replaced with the expected types +def validate_response(response: typing.Any, json_expectation: typing.Any, type_expectations: typing.Any) -> None: + # Allow for an escape hatch if the object cannot be validated + if type_expectations == "no_validate": + return + + if ( + not isinstance(response, list) + and not isinstance(response, dict) + and not issubclass(type(response), pydantic.BaseModel) + ): + validate_field( + response=response, + json_expectation=json_expectation, + type_expectation=type_expectations, + ) + return + + if isinstance(response, list): + assert len(response) == len(json_expectation), "Length mismatch, expected: {0}, Actual: {1}".format( + len(response), len(json_expectation) + ) + content_expectation = type_expectations + if isinstance(type_expectations, tuple): + content_expectation = type_expectations[1] + for idx, item in enumerate(response): + validate_response( + response=item, + json_expectation=json_expectation[idx], + type_expectations=content_expectation[idx], + ) + else: + response_json = response + if issubclass(type(response), pydantic.BaseModel): + response_json = response.dict(by_alias=True) + + for key, value in json_expectation.items(): + assert key in response_json, "Field {0} not found within the response object: {1}".format( + key, response_json + ) + + type_expectation = None + if type_expectations is not None and isinstance(type_expectations, dict): + type_expectation = type_expectations.get(key) + + # If your type_expectation is a tuple then you have a container field, process it as such + # Otherwise, we're just validating a single field that's a pydantic model. + if isinstance(value, dict) and not isinstance(type_expectation, tuple): + validate_response( + response=response_json[key], + json_expectation=value, + type_expectations=type_expectation, + ) + else: + validate_field( + response=response_json[key], + json_expectation=value, + type_expectation=type_expectation, + ) + + # Ensure there are no additional fields here either + del response_json[key] + assert len(response_json) == 0, "Additional fields found, expected None: {0}".format(response_json) diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py new file mode 100644 index 0000000..f3ea265 --- /dev/null +++ b/tests/utils/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/tests/utils/assets/models/__init__.py b/tests/utils/assets/models/__init__.py new file mode 100644 index 0000000..3a1c852 --- /dev/null +++ b/tests/utils/assets/models/__init__.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +from .circle import CircleParams +from .object_with_defaults import ObjectWithDefaultsParams +from .object_with_optional_field import ObjectWithOptionalFieldParams +from .shape import ShapeParams, Shape_CircleParams, Shape_SquareParams +from .square import SquareParams +from .undiscriminated_shape import UndiscriminatedShapeParams + +__all__ = [ + "CircleParams", + "ObjectWithDefaultsParams", + "ObjectWithOptionalFieldParams", + "ShapeParams", + "Shape_CircleParams", + "Shape_SquareParams", + "SquareParams", + "UndiscriminatedShapeParams", +] diff --git a/tests/utils/assets/models/circle.py b/tests/utils/assets/models/circle.py new file mode 100644 index 0000000..de001b7 --- /dev/null +++ b/tests/utils/assets/models/circle.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions +import typing_extensions +from webflow.core.serialization import FieldMetadata + + +class CircleParams(typing_extensions.TypedDict): + radius_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="radiusMeasurement")] diff --git a/tests/utils/assets/models/color.py b/tests/utils/assets/models/color.py new file mode 100644 index 0000000..2aa2c4c --- /dev/null +++ b/tests/utils/assets/models/color.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing + +Color = typing.Union[typing.Literal["red", "blue"], typing.Any] diff --git a/tests/utils/assets/models/object_with_defaults.py b/tests/utils/assets/models/object_with_defaults.py new file mode 100644 index 0000000..ef14f7b --- /dev/null +++ b/tests/utils/assets/models/object_with_defaults.py @@ -0,0 +1,16 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions +import typing_extensions + + +class ObjectWithDefaultsParams(typing_extensions.TypedDict): + """ + Defines properties with default values and validation rules. + """ + + decimal: typing_extensions.NotRequired[float] + string: typing_extensions.NotRequired[str] + required_string: str diff --git a/tests/utils/assets/models/object_with_optional_field.py b/tests/utils/assets/models/object_with_optional_field.py new file mode 100644 index 0000000..1912220 --- /dev/null +++ b/tests/utils/assets/models/object_with_optional_field.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions +import typing +import typing_extensions +from webflow.core.serialization import FieldMetadata +import datetime as dt +import uuid +from .color import Color +from .shape import ShapeParams +from .undiscriminated_shape import UndiscriminatedShapeParams + + +class ObjectWithOptionalFieldParams(typing_extensions.TypedDict): + literal: typing.Literal["lit_one"] + string: typing_extensions.NotRequired[str] + integer: typing_extensions.NotRequired[int] + long_: typing_extensions.NotRequired[typing_extensions.Annotated[int, FieldMetadata(alias="long")]] + double: typing_extensions.NotRequired[float] + bool_: typing_extensions.NotRequired[typing_extensions.Annotated[bool, FieldMetadata(alias="bool")]] + datetime: typing_extensions.NotRequired[dt.datetime] + date: typing_extensions.NotRequired[dt.date] + uuid_: typing_extensions.NotRequired[typing_extensions.Annotated[uuid.UUID, FieldMetadata(alias="uuid")]] + base_64: typing_extensions.NotRequired[typing_extensions.Annotated[str, FieldMetadata(alias="base64")]] + list_: typing_extensions.NotRequired[typing_extensions.Annotated[typing.Sequence[str], FieldMetadata(alias="list")]] + set_: typing_extensions.NotRequired[typing_extensions.Annotated[typing.Set[str], FieldMetadata(alias="set")]] + map_: typing_extensions.NotRequired[typing_extensions.Annotated[typing.Dict[int, str], FieldMetadata(alias="map")]] + enum: typing_extensions.NotRequired[Color] + union: typing_extensions.NotRequired[ShapeParams] + second_union: typing_extensions.NotRequired[ShapeParams] + undiscriminated_union: typing_extensions.NotRequired[UndiscriminatedShapeParams] + any: typing.Optional[typing.Any] diff --git a/tests/utils/assets/models/shape.py b/tests/utils/assets/models/shape.py new file mode 100644 index 0000000..cf58a9b --- /dev/null +++ b/tests/utils/assets/models/shape.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations +import typing_extensions +import typing_extensions +import typing +from webflow.core.serialization import FieldMetadata + + +class Base(typing_extensions.TypedDict): + id: str + + +class Shape_CircleParams(Base): + shape_type: typing_extensions.Annotated[typing.Literal["circle"], FieldMetadata(alias="shapeType")] + radius_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="radiusMeasurement")] + + +class Shape_SquareParams(Base): + shape_type: typing_extensions.Annotated[typing.Literal["square"], FieldMetadata(alias="shapeType")] + length_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="lengthMeasurement")] + + +ShapeParams = typing.Union[Shape_CircleParams, Shape_SquareParams] diff --git a/tests/utils/assets/models/square.py b/tests/utils/assets/models/square.py new file mode 100644 index 0000000..ec068c5 --- /dev/null +++ b/tests/utils/assets/models/square.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions +import typing_extensions +from webflow.core.serialization import FieldMetadata + + +class SquareParams(typing_extensions.TypedDict): + length_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="lengthMeasurement")] diff --git a/tests/utils/assets/models/undiscriminated_shape.py b/tests/utils/assets/models/undiscriminated_shape.py new file mode 100644 index 0000000..68876a2 --- /dev/null +++ b/tests/utils/assets/models/undiscriminated_shape.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing +from .circle import CircleParams +from .square import SquareParams + +UndiscriminatedShapeParams = typing.Union[CircleParams, SquareParams] diff --git a/tests/utils/test_http_client.py b/tests/utils/test_http_client.py index 98fd3c9..8532616 100644 --- a/tests/utils/test_http_client.py +++ b/tests/utils/test_http_client.py @@ -45,3 +45,17 @@ def test_get_none_request_body() -> None: assert json_body_extras == {"see you": "later"} assert data_body_extras is None + + +def test_get_empty_json_request_body() -> None: + unrelated_request_options: RequestOptions = {"max_retries": 3} + json_body, data_body = get_request_body(json=None, data=None, request_options=unrelated_request_options, omit=None) + assert json_body is None + assert data_body is None + + json_body_extras, data_body_extras = get_request_body( + json={}, data=None, request_options=unrelated_request_options, omit=None + ) + + assert json_body_extras is None + assert data_body_extras is None diff --git a/tests/utils/test_query_encoding.py b/tests/utils/test_query_encoding.py index a5d083e..9c4591e 100644 --- a/tests/utils/test_query_encoding.py +++ b/tests/utils/test_query_encoding.py @@ -1,13 +1,37 @@ # This file was auto-generated by Fern from our API Definition. + from webflow.core.query_encoder import encode_query -def test_query_encoding() -> None: - assert encode_query({"hello world": "hello world"}) == {"hello world": "hello world"} - assert encode_query({"hello_world": {"hello": "world"}}) == {"hello_world[hello]": "world"} - assert encode_query({"hello_world": {"hello": {"world": "today"}, "test": "this"}, "hi": "there"}) == { - "hello_world[hello][world]": "today", - "hello_world[test]": "this", - "hi": "there", - } +def test_query_encoding_deep_objects() -> None: + assert encode_query({"hello world": "hello world"}) == [("hello world", "hello world")] + assert encode_query({"hello_world": {"hello": "world"}}) == [("hello_world[hello]", "world")] + assert encode_query({"hello_world": {"hello": {"world": "today"}, "test": "this"}, "hi": "there"}) == [ + ("hello_world[hello][world]", "today"), + ("hello_world[test]", "this"), + ("hi", "there"), + ] + + +def test_query_encoding_deep_object_arrays() -> None: + assert encode_query({"objects": [{"key": "hello", "value": "world"}, {"key": "foo", "value": "bar"}]}) == [ + ("objects[key]", "hello"), + ("objects[value]", "world"), + ("objects[key]", "foo"), + ("objects[value]", "bar"), + ] + assert encode_query( + {"users": [{"name": "string", "tags": ["string"]}, {"name": "string2", "tags": ["string2", "string3"]}]} + ) == [ + ("users[name]", "string"), + ("users[tags]", "string"), + ("users[name]", "string2"), + ("users[tags]", "string2"), + ("users[tags]", "string3"), + ] + + +def test_encode_query_with_none() -> None: + encoded = encode_query(None) + assert encoded == None diff --git a/tests/utils/test_serialization.py b/tests/utils/test_serialization.py new file mode 100644 index 0000000..3676b2f --- /dev/null +++ b/tests/utils/test_serialization.py @@ -0,0 +1,72 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import List, Any + +from webflow.core.serialization import convert_and_respect_annotation_metadata +from .assets.models import ShapeParams, ObjectWithOptionalFieldParams + + +UNION_TEST: ShapeParams = {"radius_measurement": 1.0, "shape_type": "circle", "id": "1"} +UNION_TEST_CONVERTED = {"shapeType": "circle", "radiusMeasurement": 1.0, "id": "1"} + + +def test_convert_and_respect_annotation_metadata() -> None: + data: ObjectWithOptionalFieldParams = { + "string": "string", + "long_": 12345, + "bool_": True, + "literal": "lit_one", + "any": "any", + } + converted = convert_and_respect_annotation_metadata( + object_=data, annotation=ObjectWithOptionalFieldParams, direction="write" + ) + assert converted == {"string": "string", "long": 12345, "bool": True, "literal": "lit_one", "any": "any"} + + +def test_convert_and_respect_annotation_metadata_in_list() -> None: + data: List[ObjectWithOptionalFieldParams] = [ + {"string": "string", "long_": 12345, "bool_": True, "literal": "lit_one", "any": "any"}, + {"string": "another string", "long_": 67890, "list_": [], "literal": "lit_one", "any": "any"}, + ] + converted = convert_and_respect_annotation_metadata( + object_=data, annotation=List[ObjectWithOptionalFieldParams], direction="write" + ) + + assert converted == [ + {"string": "string", "long": 12345, "bool": True, "literal": "lit_one", "any": "any"}, + {"string": "another string", "long": 67890, "list": [], "literal": "lit_one", "any": "any"}, + ] + + +def test_convert_and_respect_annotation_metadata_in_nested_object() -> None: + data: ObjectWithOptionalFieldParams = { + "string": "string", + "long_": 12345, + "union": UNION_TEST, + "literal": "lit_one", + "any": "any", + } + converted = convert_and_respect_annotation_metadata( + object_=data, annotation=ObjectWithOptionalFieldParams, direction="write" + ) + + assert converted == { + "string": "string", + "long": 12345, + "union": UNION_TEST_CONVERTED, + "literal": "lit_one", + "any": "any", + } + + +def test_convert_and_respect_annotation_metadata_in_union() -> None: + converted = convert_and_respect_annotation_metadata(object_=UNION_TEST, annotation=ShapeParams, direction="write") + + assert converted == UNION_TEST_CONVERTED + + +def test_convert_and_respect_annotation_metadata_with_empty_object() -> None: + data: Any = {} + converted = convert_and_respect_annotation_metadata(object_=data, annotation=ShapeParams, direction="write") + assert converted == data From 6e1ebec37eeaea1a074c282e37566562f85754be Mon Sep 17 00:00:00 2001 From: Zach Plata Date: Sun, 23 Feb 2025 19:29:08 -0600 Subject: [PATCH 05/13] Add back oauth scope, bump to 2.0.0b1 with the major fern dependency bump --- .fernignore | 1 + pyproject.toml | 2 +- src/webflow/core/client_wrapper.py | 2 +- src/webflow/types/oauth_scope.py | 186 +++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 src/webflow/types/oauth_scope.py diff --git a/.fernignore b/.fernignore index b6293ae..e83159b 100644 --- a/.fernignore +++ b/.fernignore @@ -4,3 +4,4 @@ README.md assets/ src/webflow/oauth.py +src/webflow/types/oauth_scope.py \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 66a8846..749aa8e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "webflow" -version = "1.2.1" +version = "2.0.0b1" description = "" readme = "README.md" authors = [] diff --git a/src/webflow/core/client_wrapper.py b/src/webflow/core/client_wrapper.py index 1ea63b3..84ed6fb 100644 --- a/src/webflow/core/client_wrapper.py +++ b/src/webflow/core/client_wrapper.py @@ -22,7 +22,7 @@ def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { "X-Fern-Language": "Python", "X-Fern-SDK-Name": "webflow", - "X-Fern-SDK-Version": "1.2.1", + "X-Fern-SDK-Version": "2.0.0b1", } headers["Authorization"] = f"Bearer {self._get_access_token()}" return headers diff --git a/src/webflow/types/oauth_scope.py b/src/webflow/types/oauth_scope.py new file mode 100644 index 0000000..1786f30 --- /dev/null +++ b/src/webflow/types/oauth_scope.py @@ -0,0 +1,186 @@ +import enum +import typing + +T_Result = typing.TypeVar("T_Result") + + +class OauthScope(str, enum.Enum): + AUTHORIZED_USER_READ = "authorized_user:read" + """ + read details about the authorized user + """ + + ASSETS_READ = "assets:read" + """ + read assets on the site + """ + + ASSETS_WRITE = "assets:write" + """ + write assets on a site + """ + + CMS_READ = "cms:read" + """ + read collections and items for a site + """ + + CMS_WRITE = "cms:write" + """ + write to collections and items for a site + """ + + CUSTOM_CODE_READ = "custom_code:read" + """ + read custom code on the site + """ + + CUSTOM_CODE_WRITE = "custom_code:write" + """ + modify custom code on the site + """ + + ECOMMERCE_READ = "ecommerce:read" + """ + read ecommerce data + """ + + ECOMMERCE_WRITE = "ecommerce:write" + """ + edit ecommerce data + """ + + FORMS_READ = "forms:read" + """ + read form data + """ + + FORMS_WRITE = "forms:write" + """ + write form data + """ + + PAGES_READ = "pages:read" + """ + read pages on the site + """ + + PAGES_WRITE = "pages:write" + """ + write to pages on the site + """ + + SITES_READ = "sites:read" + """ + read sites on the site + """ + + SITES_WRITE = "sites:write" + """ + modify pages on the site + """ + + USERS_READ = "users:read" + """ + read users on the site + """ + + SITE_ACTIVITY_READ = "site_activity:read" + """ + read site activity logs + """ + + USERS_WRITE = "users:write" + """ + modify users on the site + """ + + WORKSPACE_READ = "workspace:read" + """ + read workspace resource data + """ + + WORKSPACE_WRITE = "workspace:write" + """ + write workspace resource data + """ + + SITE_CONFIG_READ= "site_config:read" + """ + read site configuration data + """ + + SITE_CONFIG_WRITE= "site_config:write" + """ + write site configuration data + """ + + def visit( + self, + authorized_user_read: typing.Callable[[], T_Result], + assets_read: typing.Callable[[], T_Result], + assets_write: typing.Callable[[], T_Result], + cms_read: typing.Callable[[], T_Result], + cms_write: typing.Callable[[], T_Result], + custom_code_read: typing.Callable[[], T_Result], + custom_code_write: typing.Callable[[], T_Result], + ecommerce_read: typing.Callable[[], T_Result], + ecommerce_write: typing.Callable[[], T_Result], + forms_read: typing.Callable[[], T_Result], + forms_write: typing.Callable[[], T_Result], + pages_read: typing.Callable[[], T_Result], + pages_write: typing.Callable[[], T_Result], + sites_read: typing.Callable[[], T_Result], + sites_write: typing.Callable[[], T_Result], + users_read: typing.Callable[[], T_Result], + site_activity_read: typing.Callable[[], T_Result], + users_write: typing.Callable[[], T_Result], + workspace_read: typing.Callable[[], T_Result], + workspace_write: typing.Callable[[], T_Result], + site_config_read: typing.Callable[[], T_Result], + site_config_write: typing.Callable[[], T_Result], + ) -> T_Result: + if self is OauthScope.AUTHORIZED_USER_READ: + return authorized_user_read() + if self is OauthScope.ASSETS_READ: + return assets_read() + if self is OauthScope.ASSETS_WRITE: + return assets_write() + if self is OauthScope.CMS_READ: + return cms_read() + if self is OauthScope.CMS_WRITE: + return cms_write() + if self is OauthScope.CUSTOM_CODE_READ: + return custom_code_read() + if self is OauthScope.CUSTOM_CODE_WRITE: + return custom_code_write() + if self is OauthScope.ECOMMERCE_READ: + return ecommerce_read() + if self is OauthScope.ECOMMERCE_WRITE: + return ecommerce_write() + if self is OauthScope.FORMS_READ: + return forms_read() + if self is OauthScope.FORMS_WRITE: + return forms_write() + if self is OauthScope.PAGES_READ: + return pages_read() + if self is OauthScope.PAGES_WRITE: + return pages_write() + if self is OauthScope.SITES_READ: + return sites_read() + if self is OauthScope.SITES_WRITE: + return sites_write() + if self is OauthScope.USERS_READ: + return users_read() + if self is OauthScope.SITE_ACTIVITY_READ: + return site_activity_read() + if self is OauthScope.USERS_WRITE: + return users_write() + if self is OauthScope.WORKSPACE_READ: + return workspace_read() + if self is OauthScope.WORKSPACE_WRITE: + return workspace_write() + if self is OauthScope.SITE_CONFIG_READ: + return site_config_read() + if self is OauthScope.SITE_CONFIG_WRITE: + return site_config_write() \ No newline at end of file From a16462ede26c81220bd5089ac750c31290e29eb1 Mon Sep 17 00:00:00 2001 From: Zach Plata Date: Sun, 23 Feb 2025 19:33:29 -0600 Subject: [PATCH 06/13] Add OAuthScope to types init --- src/webflow/oauth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webflow/oauth.py b/src/webflow/oauth.py index ce06031..70b35fe 100644 --- a/src/webflow/oauth.py +++ b/src/webflow/oauth.py @@ -7,7 +7,7 @@ from .core.api_error import ApiError from .core.jsonable_encoder import jsonable_encoder from .environment import WebflowEnvironment -from .types import OauthScope +from .types.oauth_scope import OauthScope try: import pydantic.v1 as pydantic # type: ignore From a862ea856525b4539113f69a1fb8716aedcab0af Mon Sep 17 00:00:00 2001 From: Zach Plata Date: Sun, 23 Feb 2025 19:55:02 -0600 Subject: [PATCH 07/13] temporarily revert back to old test command until examples fixed --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0cbadd0..d396980 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: - name: Install Fern run: npm install -g fern-api - name: Test - run: fern test --command "poetry run pytest -rP ." + run: fern test --command "poetry run pytest -rP ./tests/custom/" publish: needs: [compile, test] From 264cf576c6efe5544239870e357e0787bb009158 Mon Sep 17 00:00:00 2001 From: Zach Plata Date: Fri, 19 Sep 2025 13:25:49 -0500 Subject: [PATCH 08/13] patch: set httpcore to fix vulnerability with downstream h11 --- poetry.lock | 20 ++++++++++---------- pyproject.toml | 1 + 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/poetry.lock b/poetry.lock index a563308..658601b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "annotated-types" @@ -74,29 +74,29 @@ test = ["pytest (>=6)"] [[package]] name = "h11" -version = "0.14.0" +version = "0.16.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, ] [[package]] name = "httpcore" -version = "1.0.7" +version = "1.0.9" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, - {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, + {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, + {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, ] [package.dependencies] certifi = "*" -h11 = ">=0.13,<0.15" +h11 = ">=0.16" [package.extras] asyncio = ["anyio (>=4.0,<5.0)"] @@ -537,4 +537,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "6f6c191c1028d17a97fdfa84cedfd3cef94b5d63d98b8c1d333b3398eeea9055" +content-hash = "2974ad2d485417c468bff08c2d5526b20e5e4790deaffc5363b3c831bebca3b3" diff --git a/pyproject.toml b/pyproject.toml index 749aa8e..3da9d50 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ Repository = 'https://github.com/webflow/webflow-python' [tool.poetry.dependencies] python = "^3.8" httpx = ">=0.21.2" +httpcore = "1.0.9" pydantic = ">= 1.9.2" pydantic-core = "^2.18.2" typing_extensions = ">= 4.0.0" From cf820bebb160e4bf7631eda124539435819d4cfb Mon Sep 17 00:00:00 2001 From: Zach Plata Date: Mon, 22 Sep 2025 18:36:50 -0500 Subject: [PATCH 09/13] bump to 2.0.0b2 --- pyproject.toml | 2 +- src/webflow/core/client_wrapper.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3da9d50..58c9529 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "webflow" -version = "2.0.0b1" +version = "2.0.0b2" description = "" readme = "README.md" authors = [] diff --git a/src/webflow/core/client_wrapper.py b/src/webflow/core/client_wrapper.py index 84ed6fb..a04487e 100644 --- a/src/webflow/core/client_wrapper.py +++ b/src/webflow/core/client_wrapper.py @@ -22,7 +22,7 @@ def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { "X-Fern-Language": "Python", "X-Fern-SDK-Name": "webflow", - "X-Fern-SDK-Version": "2.0.0b1", + "X-Fern-SDK-Version": "2.0.0b2", } headers["Authorization"] = f"Bearer {self._get_access_token()}" return headers From 6ca871e07bfa9390284a78cf9156982bb6e066ec Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Thu, 5 Mar 2026 03:22:51 +0000 Subject: [PATCH 10/13] SDK regeneration --- .github/workflows/ci.yml | 8 +- .mock/definition/__package__.yml | 2051 ++++++++-- .mock/definition/accessGroups.yml | 80 - .mock/definition/api.yml | 9 +- .mock/definition/assets.yml | 178 +- .mock/definition/collections.yml | 204 +- .mock/definition/collections/fields.yml | 131 +- .mock/definition/collections/items.yml | 1087 +++-- .mock/definition/comments.yml | 41 + .mock/definition/components.yml | 244 +- .mock/definition/ecommerce.yml | 5 +- .mock/definition/forms.yml | 115 +- .mock/definition/inventory.yml | 62 +- .mock/definition/items.yml | 112 + .mock/definition/orders.yml | 604 ++- .mock/definition/pages.yml | 319 +- .mock/definition/pages/scripts.yml | 73 +- .mock/definition/products.yml | 278 +- .mock/definition/scripts.yml | 83 +- .mock/definition/sites.yml | 113 +- .mock/definition/sites/activityLogs.yml | 24 +- .mock/definition/sites/comments.yml | 352 ++ .mock/definition/sites/forms.yml | 316 ++ .mock/definition/sites/plans.yml | 12 +- .mock/definition/sites/redirects.yml | 57 +- .mock/definition/sites/robotsTxt.yml | 229 ++ .mock/definition/sites/scripts.yml | 80 +- .mock/definition/sites/wellKnown.yml | 130 + .mock/definition/token.yml | 7 +- .mock/definition/users.yml | 392 -- .mock/definition/webhooks.yml | 15 +- .mock/definition/workspaces/auditLogs.yml | 126 + .mock/fern.config.json | 2 +- poetry.lock | 144 +- pyproject.toml | 3 +- reference.md | 3622 ++++++++++++----- src/webflow/__init__.py | 286 +- src/webflow/client.py | 51 +- src/webflow/core/client_wrapper.py | 43 +- src/webflow/environment.py | 18 +- src/webflow/resources/__init__.py | 22 +- .../resources/access_groups/__init__.py | 5 - .../resources/access_groups/types/__init__.py | 5 - .../types/access_groups_list_request_sort.py | 5 - src/webflow/resources/assets/client.py | 92 +- src/webflow/resources/collections/__init__.py | 20 +- src/webflow/resources/collections/client.py | 108 +- .../collections/resources/__init__.py | 20 +- .../collections/resources/fields/__init__.py | 3 - .../collections/resources/fields/client.py | 152 +- .../resources/fields/types/__init__.py | 5 - .../collections/resources/items/__init__.py | 18 +- .../collections/resources/items/client.py | 556 ++- .../resources/items/types/__init__.py | 18 +- .../resources/items/types/item_i_ds.py | 25 + .../items/types/item_i_ds_with_locales.py | 24 + ...=> items_create_item_live_request_body.py} | 2 +- ...t.py => items_create_item_request_body.py} | 2 +- ...ms_delete_items_live_request_items_item.py | 6 +- .../items/types/items_publish_item_request.py | 7 + ...s_publish_item_request_items_items_item.py | 31 + .../types/items_update_items_response.py | 7 + src/webflow/resources/components/client.py | 250 +- .../types/component_dom_write_nodes_item.py | 13 +- src/webflow/resources/ecommerce/client.py | 2 + src/webflow/resources/forms/client.py | 302 +- src/webflow/resources/inventory/__init__.py | 4 +- src/webflow/resources/inventory/client.py | 72 +- .../resources/inventory/types/__init__.py | 3 +- .../types/ecomm_inventory_changed_payload.py | 25 + src/webflow/resources/orders/client.py | 34 +- src/webflow/resources/pages/__init__.py | 10 +- src/webflow/resources/pages/client.py | 376 +- .../pages/resources/scripts/client.py | 62 +- src/webflow/resources/pages/types/__init__.py | 4 +- .../pages/types/page_dom_write_nodes_item.py | 13 +- .../types/page_metadata_write_open_graph.py | 47 + .../pages/types/page_metadata_write_seo.py | 31 + src/webflow/resources/products/__init__.py | 4 +- src/webflow/resources/products/client.py | 362 +- .../resources/products/types/__init__.py | 4 +- .../types/product_sku_create_product.py | 22 + .../products/types/product_sku_create_sku.py | 22 + .../types/products_create_sku_response.py | 2 +- src/webflow/resources/scripts/client.py | 70 +- src/webflow/resources/sites/__init__.py | 37 +- src/webflow/resources/sites/client.py | 66 +- .../resources/sites/resources/__init__.py | 29 +- .../sites/resources/activity_logs/client.py | 34 +- .../sites/resources/comments/__init__.py | 19 + .../sites/resources/comments/client.py | 937 +++++ .../resources/comments/types/__init__.py | 17 + ...ents_get_comment_thread_request_sort_by.py | 5 + ...s_get_comment_thread_request_sort_order.py | 5 + ...ts_list_comment_replies_request_sort_by.py | 5 + ...list_comment_replies_request_sort_order.py | 5 + ...ts_list_comment_threads_request_sort_by.py | 5 + ...list_comment_threads_request_sort_order.py | 5 + .../sites/resources/forms/__init__.py} | 3 - .../resources/forms}/client.py | 535 +-- .../resources/sites/resources/plans/client.py | 6 + .../sites/resources/redirects/client.py | 44 +- .../sites/resources/robots_txt/__init__.py} | 3 - .../sites/resources/robots_txt/client.py | 1050 +++++ .../sites/resources/scripts/client.py | 88 +- .../sites/resources/well_known/__init__.py | 5 + .../sites/resources/well_known/client.py | 534 +++ .../resources/well_known/types/__init__.py | 5 + .../types/well_known_file_content_type.py | 5 + src/webflow/resources/token/client.py | 4 + src/webflow/resources/users/__init__.py | 5 - src/webflow/resources/users/types/__init__.py | 6 - .../users/types/users_list_request_sort.py | 19 - .../users/types/users_update_request_data.py | 38 - src/webflow/resources/webhooks/client.py | 8 + src/webflow/resources/workspaces/__init__.py | 13 + src/webflow/resources/workspaces/client.py | 18 + .../workspaces/resources/__init__.py | 10 + .../resources/audit_logs/__init__.py | 5 + .../resources/audit_logs}/client.py | 213 +- .../resources/audit_logs/types/__init__.py | 6 + ...workspace_audit_logs_request_event_type.py | 15 + ...workspace_audit_logs_request_sort_order.py | 5 + src/webflow/types/__init__.py | 295 +- src/webflow/types/access_group.py | 49 - src/webflow/types/access_group_list.py | 51 - src/webflow/types/application.py | 38 +- src/webflow/types/asset.py | 14 +- src/webflow/types/asset_variant.py | 24 +- src/webflow/types/assets.py | 2 + src/webflow/types/bulk_collection_item.py | 4 +- src/webflow/types/collection.py | 10 +- src/webflow/types/collection_item_changed.py | 33 + src/webflow/types/collection_item_created.py | 33 + .../types/collection_item_list_pagination.py | 6 +- .../types/collection_item_published.py | 29 + src/webflow/types/collection_item_removed.py | 32 + .../types/collection_item_removed_payload.py | 69 + ...ection_item_removed_payload_field_data.py} | 12 +- .../types/collection_item_unpublished.py | 32 + .../collection_item_unpublished_payload.py | 69 + ...ion_item_unpublished_payload_field_data.py | 20 + src/webflow/types/comment.py | 33 + src/webflow/types/comment_payload.py | 114 + ...oups_item.py => comment_payload_author.py} | 20 +- .../comment_payload_mentioned_users_item.py | 34 + src/webflow/types/comment_reply.py | 89 + src/webflow/types/comment_reply_author.py | 32 + src/webflow/types/comment_reply_list.py | 26 + .../types/comment_reply_list_pagination.py | 32 + .../comment_reply_mentioned_users_item.py | 32 + src/webflow/types/comment_thread.py | 92 + src/webflow/types/comment_thread_author.py | 34 + src/webflow/types/comment_thread_list.py | 26 + .../types/comment_thread_list_pagination.py | 32 + .../comment_thread_mentioned_users_item.py | 34 + src/webflow/types/component_dom.py | 2 +- src/webflow/types/component_node.py | 16 +- .../{users_not_enabled.py => conflict.py} | 2 +- src/webflow/types/conflict_error_body.py | 7 - src/webflow/types/custom_role.py | 33 + .../types/custom_role_audit_log_item.py | 26 + ...stom_role_audit_log_item_event_sub_type.py | 7 + src/webflow/types/dom.py | 14 + src/webflow/types/field.py | 6 + src/webflow/types/field_create.py | 8 + src/webflow/types/field_type.py | 6 +- src/webflow/types/field_validations.py | 28 + ...field_validations_additional_properties.py | 10 + ...tional_properties_additional_properties.py | 23 + src/webflow/types/forbidden_error_body.py | 4 +- src/webflow/types/form_submission_trigger.py | 36 + .../types/form_submission_trigger_payload.py | 74 + ..._submission_trigger_payload_schema_item.py | 41 + ..._trigger_payload_schema_item_field_type.py | 8 + src/webflow/types/image_node.py | 10 +- src/webflow/types/image_node_image.py | 4 + ..._list_items_live_request_last_published.py | 28 + ...items_list_items_request_last_published.py | 28 + src/webflow/types/metadata.py | 27 + src/webflow/types/metadata_options_item.py | 31 + src/webflow/types/new_order.py | 33 + src/webflow/types/node.py | 102 +- src/webflow/types/option_field.py | 58 + src/webflow/types/order.py | 6 +- src/webflow/types/order_billing_address.py | 78 + .../types/order_billing_address_japan_type.py | 5 + .../types/order_billing_address_type.py | 5 + src/webflow/types/order_shipping_address.py | 78 + .../order_shipping_address_japan_type.py | 5 + .../types/order_shipping_address_type.py | 5 + src/webflow/types/page.py | 8 +- src/webflow/types/page_created_webhook.py | 36 + .../types/page_created_webhook_payload.py | 30 + src/webflow/types/page_deleted_webhook.py | 36 + .../types/page_deleted_webhook_payload.py | 30 + .../types/page_metadata_updated_webhook.py | 36 + .../page_metadata_updated_webhook_payload.py | 30 + src/webflow/types/pagination.py | 6 +- src/webflow/types/payload.py | 67 + src/webflow/types/payload_field_data.py | 20 + src/webflow/types/product_field_data.py | 4 +- src/webflow/types/reference_field.py | 62 + src/webflow/types/reference_field_metadata.py | 28 + src/webflow/types/reference_field_type.py | 5 + src/webflow/types/registered_script_list.py | 2 + src/webflow/types/robots.py | 32 + src/webflow/types/robots_rules_item.py | 34 + src/webflow/types/search_button_node.py | 36 + src/webflow/types/search_button_node_write.py | 33 + src/webflow/types/select.py | 34 + src/webflow/types/select_node.py | 37 + src/webflow/types/select_node_choices_item.py | 27 + .../types/select_node_write_choices_item.py | 27 + src/webflow/types/setting_change.py | 25 + .../types/setting_change_audit_log_item.py | 25 + .../types/single_locale_created_payload.py | 57 + ...ingle_locale_created_payload_field_data.py | 20 + src/webflow/types/site_membership.py | 56 + .../types/site_membership_audit_log_item.py | 26 + ...embership_audit_log_item_event_sub_type.py | 7 + src/webflow/types/site_publish.py | 36 + src/webflow/types/site_publish_payload.py | 50 + src/webflow/types/sku_field_data.py | 30 +- ...sku_field_data_ec_sku_subscription_plan.py | 4 + src/webflow/types/sku_field_data_price.py | 5 + src/webflow/types/static_field.py | 56 + .../static_field_type.py} | 5 +- src/webflow/types/submit_button_node.py | 43 + src/webflow/types/submit_button_node_write.py | 40 + src/webflow/types/text.py | 4 + src/webflow/types/text_input_node.py | 36 + src/webflow/types/text_input_node_write.py | 33 + src/webflow/types/text_node.py | 10 +- src/webflow/types/text_node_text.py | 4 + src/webflow/types/trigger_type.py | 5 +- src/webflow/types/updated_order.py | 33 + src/webflow/types/user.py | 81 - src/webflow/types/user_access.py | 33 + .../types/user_access_audit_log_item.py | 26 + ...er_access_audit_log_item_event_sub_type.py | 5 + .../types/user_access_groups_item_type.py | 5 - src/webflow/types/user_data_data.py | 50 - src/webflow/types/user_list.py | 47 - src/webflow/types/user_status.py | 5 - src/webflow/types/webhook_list.py | 4 +- src/webflow/types/workspace_audit_log_item.py | 162 + .../types/workspace_audit_log_item_actor.py | 20 + ..._log_item_payload_setting_change_method.py | 5 + ...payload_site_membership_granular_access.py | 22 + ...log_item_payload_site_membership_method.py | 7 + ...t_log_item_payload_site_membership_site.py | 20 + ...tem_payload_site_membership_target_user.py | 20 + ..._item_payload_site_membership_user_type.py | 7 + ...dit_log_item_payload_user_access_method.py | 7 + ...tem_payload_workspace_invitation_method.py | 7 + ...ayload_workspace_invitation_target_user.py | 20 + ..._workspace_invitation_target_users_item.py | 20 + ..._payload_workspace_invitation_user_type.py | 7 + ...tem_payload_workspace_membership_method.py | 7 + ...ayload_workspace_membership_target_user.py | 20 + ..._payload_workspace_membership_user_type.py | 7 + .../workspace_audit_log_item_workspace.py | 20 + .../types/workspace_audit_log_response.py | 22 + src/webflow/types/workspace_invitation.py | 57 + .../workspace_invitation_audit_log_item.py | 26 + ...nvitation_audit_log_item_event_sub_type.py | 15 + src/webflow/types/workspace_membership.py | 49 + .../workspace_membership_audit_log_item.py | 26 + ...embership_audit_log_item_event_sub_type.py | 7 + tests/collections/test_fields.py | 35 +- tests/collections/test_items.py | 442 +- tests/conftest.py | 15 +- tests/sites/test_activity_logs.py | 6 +- tests/sites/test_comments.py | 242 ++ tests/sites/test_forms.py | 193 + tests/sites/test_redirects.py | 4 +- tests/sites/test_robots_txt.py | 145 + tests/sites/test_scripts.py | 8 +- tests/sites/test_well_known.py | 40 + tests/test_access_groups.py | 49 - tests/test_assets.py | 129 +- tests/test_collections.py | 403 +- tests/test_components.py | 113 +- tests/test_forms.py | 53 +- tests/test_inventory.py | 8 +- tests/test_orders.py | 204 +- tests/test_pages.py | 162 +- tests/test_products.py | 367 +- tests/test_scripts.py | 6 +- tests/test_sites.py | 24 +- tests/test_token.py | 2 +- tests/test_users.py | 301 -- tests/test_webhooks.py | 4 +- tests/workspaces/__init__.py | 2 + tests/workspaces/test_audit_logs.py | 61 + 296 files changed, 20285 insertions(+), 5530 deletions(-) delete mode 100644 .mock/definition/accessGroups.yml create mode 100644 .mock/definition/comments.yml create mode 100644 .mock/definition/items.yml create mode 100644 .mock/definition/sites/comments.yml create mode 100644 .mock/definition/sites/forms.yml create mode 100644 .mock/definition/sites/robotsTxt.yml create mode 100644 .mock/definition/sites/wellKnown.yml delete mode 100644 .mock/definition/users.yml create mode 100644 .mock/definition/workspaces/auditLogs.yml delete mode 100644 src/webflow/resources/access_groups/__init__.py delete mode 100644 src/webflow/resources/access_groups/types/__init__.py delete mode 100644 src/webflow/resources/access_groups/types/access_groups_list_request_sort.py delete mode 100644 src/webflow/resources/collections/resources/fields/types/__init__.py create mode 100644 src/webflow/resources/collections/resources/items/types/item_i_ds.py create mode 100644 src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py rename src/webflow/resources/collections/resources/items/types/{items_create_item_live_request.py => items_create_item_live_request_body.py} (69%) rename src/webflow/resources/collections/resources/items/types/{items_create_item_request.py => items_create_item_request_body.py} (70%) create mode 100644 src/webflow/resources/collections/resources/items/types/items_publish_item_request.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py create mode 100644 src/webflow/resources/collections/resources/items/types/items_update_items_response.py create mode 100644 src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py create mode 100644 src/webflow/resources/pages/types/page_metadata_write_open_graph.py create mode 100644 src/webflow/resources/pages/types/page_metadata_write_seo.py create mode 100644 src/webflow/resources/products/types/product_sku_create_product.py create mode 100644 src/webflow/resources/products/types/product_sku_create_sku.py create mode 100644 src/webflow/resources/sites/resources/comments/__init__.py create mode 100644 src/webflow/resources/sites/resources/comments/client.py create mode 100644 src/webflow/resources/sites/resources/comments/types/__init__.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_by.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_order.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_by.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_order.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_by.py create mode 100644 src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_order.py rename src/webflow/{types/user_limit_reached.py => resources/sites/resources/forms/__init__.py} (51%) rename src/webflow/resources/{users => sites/resources/forms}/client.py (74%) rename src/webflow/{types/duplicate_user_email.py => resources/sites/resources/robots_txt/__init__.py} (50%) create mode 100644 src/webflow/resources/sites/resources/robots_txt/client.py create mode 100644 src/webflow/resources/sites/resources/well_known/__init__.py create mode 100644 src/webflow/resources/sites/resources/well_known/client.py create mode 100644 src/webflow/resources/sites/resources/well_known/types/__init__.py create mode 100644 src/webflow/resources/sites/resources/well_known/types/well_known_file_content_type.py delete mode 100644 src/webflow/resources/users/__init__.py delete mode 100644 src/webflow/resources/users/types/__init__.py delete mode 100644 src/webflow/resources/users/types/users_list_request_sort.py delete mode 100644 src/webflow/resources/users/types/users_update_request_data.py create mode 100644 src/webflow/resources/workspaces/__init__.py create mode 100644 src/webflow/resources/workspaces/client.py create mode 100644 src/webflow/resources/workspaces/resources/__init__.py create mode 100644 src/webflow/resources/workspaces/resources/audit_logs/__init__.py rename src/webflow/resources/{access_groups => workspaces/resources/audit_logs}/client.py (52%) create mode 100644 src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py create mode 100644 src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_event_type.py create mode 100644 src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_sort_order.py delete mode 100644 src/webflow/types/access_group.py delete mode 100644 src/webflow/types/access_group_list.py create mode 100644 src/webflow/types/collection_item_changed.py create mode 100644 src/webflow/types/collection_item_created.py create mode 100644 src/webflow/types/collection_item_published.py create mode 100644 src/webflow/types/collection_item_removed.py create mode 100644 src/webflow/types/collection_item_removed_payload.py rename src/webflow/types/{user_data.py => collection_item_removed_payload_field_data.py} (71%) create mode 100644 src/webflow/types/collection_item_unpublished.py create mode 100644 src/webflow/types/collection_item_unpublished_payload.py create mode 100644 src/webflow/types/collection_item_unpublished_payload_field_data.py create mode 100644 src/webflow/types/comment.py create mode 100644 src/webflow/types/comment_payload.py rename src/webflow/types/{user_access_groups_item.py => comment_payload_author.py} (50%) create mode 100644 src/webflow/types/comment_payload_mentioned_users_item.py create mode 100644 src/webflow/types/comment_reply.py create mode 100644 src/webflow/types/comment_reply_author.py create mode 100644 src/webflow/types/comment_reply_list.py create mode 100644 src/webflow/types/comment_reply_list_pagination.py create mode 100644 src/webflow/types/comment_reply_mentioned_users_item.py create mode 100644 src/webflow/types/comment_thread.py create mode 100644 src/webflow/types/comment_thread_author.py create mode 100644 src/webflow/types/comment_thread_list.py create mode 100644 src/webflow/types/comment_thread_list_pagination.py create mode 100644 src/webflow/types/comment_thread_mentioned_users_item.py rename src/webflow/types/{users_not_enabled.py => conflict.py} (63%) delete mode 100644 src/webflow/types/conflict_error_body.py create mode 100644 src/webflow/types/custom_role.py create mode 100644 src/webflow/types/custom_role_audit_log_item.py create mode 100644 src/webflow/types/custom_role_audit_log_item_event_sub_type.py create mode 100644 src/webflow/types/field_create.py create mode 100644 src/webflow/types/field_validations.py create mode 100644 src/webflow/types/field_validations_additional_properties.py create mode 100644 src/webflow/types/field_validations_additional_properties_additional_properties.py create mode 100644 src/webflow/types/form_submission_trigger.py create mode 100644 src/webflow/types/form_submission_trigger_payload.py create mode 100644 src/webflow/types/form_submission_trigger_payload_schema_item.py create mode 100644 src/webflow/types/form_submission_trigger_payload_schema_item_field_type.py create mode 100644 src/webflow/types/items_list_items_live_request_last_published.py create mode 100644 src/webflow/types/items_list_items_request_last_published.py create mode 100644 src/webflow/types/metadata.py create mode 100644 src/webflow/types/metadata_options_item.py create mode 100644 src/webflow/types/new_order.py create mode 100644 src/webflow/types/option_field.py create mode 100644 src/webflow/types/order_billing_address.py create mode 100644 src/webflow/types/order_billing_address_japan_type.py create mode 100644 src/webflow/types/order_billing_address_type.py create mode 100644 src/webflow/types/order_shipping_address.py create mode 100644 src/webflow/types/order_shipping_address_japan_type.py create mode 100644 src/webflow/types/order_shipping_address_type.py create mode 100644 src/webflow/types/page_created_webhook.py create mode 100644 src/webflow/types/page_created_webhook_payload.py create mode 100644 src/webflow/types/page_deleted_webhook.py create mode 100644 src/webflow/types/page_deleted_webhook_payload.py create mode 100644 src/webflow/types/page_metadata_updated_webhook.py create mode 100644 src/webflow/types/page_metadata_updated_webhook_payload.py create mode 100644 src/webflow/types/payload.py create mode 100644 src/webflow/types/payload_field_data.py create mode 100644 src/webflow/types/reference_field.py create mode 100644 src/webflow/types/reference_field_metadata.py create mode 100644 src/webflow/types/reference_field_type.py create mode 100644 src/webflow/types/robots.py create mode 100644 src/webflow/types/robots_rules_item.py create mode 100644 src/webflow/types/search_button_node.py create mode 100644 src/webflow/types/search_button_node_write.py create mode 100644 src/webflow/types/select.py create mode 100644 src/webflow/types/select_node.py create mode 100644 src/webflow/types/select_node_choices_item.py create mode 100644 src/webflow/types/select_node_write_choices_item.py create mode 100644 src/webflow/types/setting_change.py create mode 100644 src/webflow/types/setting_change_audit_log_item.py create mode 100644 src/webflow/types/single_locale_created_payload.py create mode 100644 src/webflow/types/single_locale_created_payload_field_data.py create mode 100644 src/webflow/types/site_membership.py create mode 100644 src/webflow/types/site_membership_audit_log_item.py create mode 100644 src/webflow/types/site_membership_audit_log_item_event_sub_type.py create mode 100644 src/webflow/types/site_publish.py create mode 100644 src/webflow/types/site_publish_payload.py create mode 100644 src/webflow/types/static_field.py rename src/webflow/{resources/collections/resources/fields/types/field_create_type.py => types/static_field_type.py} (82%) create mode 100644 src/webflow/types/submit_button_node.py create mode 100644 src/webflow/types/submit_button_node_write.py create mode 100644 src/webflow/types/text_input_node.py create mode 100644 src/webflow/types/text_input_node_write.py create mode 100644 src/webflow/types/updated_order.py delete mode 100644 src/webflow/types/user.py create mode 100644 src/webflow/types/user_access.py create mode 100644 src/webflow/types/user_access_audit_log_item.py create mode 100644 src/webflow/types/user_access_audit_log_item_event_sub_type.py delete mode 100644 src/webflow/types/user_access_groups_item_type.py delete mode 100644 src/webflow/types/user_data_data.py delete mode 100644 src/webflow/types/user_list.py delete mode 100644 src/webflow/types/user_status.py create mode 100644 src/webflow/types/workspace_audit_log_item.py create mode 100644 src/webflow/types/workspace_audit_log_item_actor.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_setting_change_method.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_site_membership_granular_access.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_site_membership_method.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_site_membership_user_type.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_user_access_method.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_method.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_users_item.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_user_type.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_membership_method.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py create mode 100644 src/webflow/types/workspace_audit_log_item_payload_workspace_membership_user_type.py create mode 100644 src/webflow/types/workspace_audit_log_item_workspace.py create mode 100644 src/webflow/types/workspace_audit_log_response.py create mode 100644 src/webflow/types/workspace_invitation.py create mode 100644 src/webflow/types/workspace_invitation_audit_log_item.py create mode 100644 src/webflow/types/workspace_invitation_audit_log_item_event_sub_type.py create mode 100644 src/webflow/types/workspace_membership.py create mode 100644 src/webflow/types/workspace_membership_audit_log_item.py create mode 100644 src/webflow/types/workspace_membership_audit_log_item_event_sub_type.py create mode 100644 tests/sites/test_comments.py create mode 100644 tests/sites/test_forms.py create mode 100644 tests/sites/test_robots_txt.py create mode 100644 tests/sites/test_well_known.py delete mode 100644 tests/test_access_groups.py delete mode 100644 tests/test_users.py create mode 100644 tests/workspaces/__init__.py create mode 100644 tests/workspaces/test_audit_logs.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d396980..14569f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: ci on: [push] jobs: compile: - runs-on: ubuntu-24.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repo uses: actions/checkout@v3 @@ -19,7 +19,7 @@ jobs: - name: Compile run: poetry run mypy . test: - runs-on: ubuntu-24.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repo uses: actions/checkout@v3 @@ -36,12 +36,12 @@ jobs: - name: Install Fern run: npm install -g fern-api - name: Test - run: fern test --command "poetry run pytest -rP ./tests/custom/" + run: fern test --command "poetry run pytest -rP ." publish: needs: [compile, test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') - runs-on: ubuntu-24.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repo uses: actions/checkout@v3 diff --git a/.mock/definition/__package__.yml b/.mock/definition/__package__.yml index db84636..250c1b4 100644 --- a/.mock/definition/__package__.yml +++ b/.mock/definition/__package__.yml @@ -67,18 +67,24 @@ errors: ConflictError: status-code: 409 type: unknown - docs: Site is published to multiple domains at different times + docs: Collection already exists examples: + - value: + code: duplicate_collection + message: Collection already exists - value: message: '''Site is published to multiple domains at different times' + - value: + code: conflict + message: >- + Conflict: Conflict with server data: Live PATCH updates can't be + applied to items that have never been published - value: code: custom_code_max_registered_scripts message: The maximum number of registered scripts has been reached. - value: code: forms_require_republish message: To access this feature, the site needs to be republished. - - value: - key: value - value: code: ecommerce_not_enabled message: Ecommerce is not yet initialized @@ -87,7 +93,7 @@ types: discriminated: false union: - InvalidScopes - - UsersNotEnabled + - NotEnterprisePlanSite source: openapi: ../../../openapi/referenced-specs/v2.yml BadRequestErrorBody: @@ -97,11 +103,24 @@ types: - NoDomains source: openapi: ../../../openapi/referenced-specs/v2.yml - ConflictErrorBody: - discriminated: false - union: - - DuplicateUserEmail - - UserLimitReached + ItemsListItemsRequestLastPublished: + properties: + lte: + type: optional + docs: Filter items last published before this date + gte: + type: optional + docs: Filter items last published after this date + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ItemsListItemsLiveRequestLastPublished: + properties: + lte: + type: optional + docs: Filter items last published before this date + gte: + type: optional + docs: Filter items last published after this date source: openapi: ../../../openapi/referenced-specs/v2.yml AuthorizedUser: @@ -173,7 +192,24 @@ types: docs: Array of errors source: openapi: ../../../openapi/referenced-specs/v2.yml - Application: unknown + Application: + properties: + id: + type: optional + docs: Unique identifier for the Application + description: + type: optional + docs: Application description provided by the developer + homepage: + type: optional + docs: Application homepage URL provided by the developer + validation: + format: uri + displayName: + type: optional + docs: Application name provided by the developer + source: + openapi: ../../../openapi/referenced-specs/v2.yml AuthorizationAuthorizationAuthorizedTo: properties: siteIds: @@ -232,6 +268,7 @@ types: lastPublished: type: optional docs: The date the custom domain was last published to + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml Locale: @@ -329,6 +366,330 @@ types: openapi: ../../../openapi/referenced-specs/v2.yml InvalidScopes: unknown NotEnterprisePlanWorkspace: unknown + WorkspaceAuditLogItemPayloadUserAccessMethod: + enum: + - dashboard + - sso + - api + - google + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + User access: + properties: + method: optional + location: + type: optional + docs: The geolocation based on the logged IP address + ipAddress: + type: optional + docs: The captured IP address of the user + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UserAccessAuditLogItemEventSubType: + enum: + - login + - logout + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UserAccessAuditLogItem: + properties: + eventSubType: optional + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Custom role: + properties: + roleName: + type: optional + docs: The name of the custom role + previousRoleName: + type: optional + docs: The previous name of the custom role + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CustomRoleAuditLogItemEventSubType: + enum: + - role_created + - role_updated + - role_deleted + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CustomRoleAuditLogItem: + properties: + eventSubType: optional + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser: + properties: + id: optional + email: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod: + enum: + - sso + - dashboard + - admin + - access_request + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType: + enum: + - member + - guest + - reviewer + - client + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Workspace membership: + properties: + targetUser: optional + method: optional + userType: optional + roleName: + type: optional + docs: The name of the role that was assigned to the user + previousRoleName: + type: optional + docs: The previous role that the user had + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceMembershipAuditLogItemEventSubType: + enum: + - user_added + - user_removed + - user_role_updated + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceMembershipAuditLogItem: + properties: + eventSubType: optional + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadSiteMembershipSite: + properties: + id: optional + slug: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItemPayloadSiteMembershipTargetUser: + properties: + id: optional + email: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItemPayloadSiteMembershipMethod: + enum: + - sso + - invite + - scim + - dashboard + - admin + - access_request + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadSiteMembershipUserType: + enum: + - member + - guest + - reviewer + - client + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess: + properties: + id: optional + name: optional + type: optional> + restricted: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Site membership: + properties: + site: optional + targetUser: optional + method: optional + userType: optional + roleName: + type: optional + docs: The name of the role that was assigned to the user + previousRoleName: + type: optional + docs: The previous role that the user had + granularAccess: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SiteMembershipAuditLogItemEventSubType: + enum: + - user_added + - user_removed + - user_role_updated + - user_granular_access_updated + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SiteMembershipAuditLogItem: + properties: + eventSubType: optional + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser: + properties: + id: optional + email: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod: + enum: + - sso + - dashboard + - admin + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType: + enum: + - member + - guest + - reviewer + - client + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem: + properties: + id: optional + email: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Workspace invitation: + properties: + targetUser: optional + method: optional + userType: optional + roleName: + type: optional + docs: The name of the role that was assigned to the user + previousRoleName: + type: optional + docs: The previous role that the user had + targetUsers: >- + optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceInvitationAuditLogItemEventSubType: + enum: + - invite_sent + - invite_accepted + - invite_updated + - invite_canceled + - invite_declined + - access_request_accepted + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceInvitationAuditLogItem: + properties: + eventSubType: optional + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemPayloadSettingChangeMethod: + enum: + - dashboard + - admin + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Setting change: + properties: + setting: optional> + previousValue: optional + value: optional + method: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SettingChangeAuditLogItem: + properties: + eventSubType: optional> + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogItemActor: + properties: + id: optional + email: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItemWorkspace: + properties: + id: optional + slug: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + WorkspaceAuditLogItem: + discriminant: eventType + base-properties: + timestamp: optional + actor: optional + workspace: optional + union: + user_access: + type: UserAccessAuditLogItem + custom_role: + type: CustomRoleAuditLogItem + workspace_membership: + type: WorkspaceMembershipAuditLogItem + site_membership: + type: SiteMembershipAuditLogItem + workspace_invitation: + type: WorkspaceInvitationAuditLogItem + workspace_setting: + type: SettingChangeAuditLogItem + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Pagination: + docs: Pagination object + properties: + limit: + type: optional + docs: The limit used for pagination + access: read-only + offset: + type: optional + docs: The offset used for pagination + access: read-only + total: + type: optional + docs: The total number of records + access: read-only + source: + openapi: ../../../openapi/referenced-specs/v2.yml + WorkspaceAuditLogResponse: + properties: + items: optional> + pagination: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml Sites: properties: sites: optional> @@ -348,6 +709,7 @@ types: id: type: optional docs: The ID of the specific redirect rule + access: read-only fromUrl: type: optional docs: The source URL path that will be redirected. @@ -356,20 +718,6 @@ types: docs: The target URL path where the user or client will be redirected. source: openapi: ../../../openapi/referenced-specs/v2.yml - Pagination: - docs: Pagination object - properties: - limit: - type: optional - docs: The limit used for pagination - offset: - type: optional - docs: The offset used for pagination - total: - type: optional - docs: The total number of records - source: - openapi: ../../../openapi/referenced-specs/v2.yml Redirects: docs: Site redirects response properties: @@ -440,6 +788,31 @@ types: docs: URL for more information about Webflow hosting plan pricing. source: openapi: ../../../openapi/referenced-specs/v2.yml + RobotsRulesItem: + properties: + userAgent: + type: string + docs: The user agent the rules apply to. + allows: + type: optional> + docs: List of paths allowed for this user agent. + disallows: + type: optional> + docs: List of paths disallowed for this user agent. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Robots: + docs: The robots.txt file for a given site + properties: + rules: + type: optional> + docs: List of rules for user agents. + sitemap: + type: optional + docs: URL to the sitemap. + source: + openapi: ../../../openapi/referenced-specs/v2.yml SiteActivityLogItemEvent: enum: - styles_modified @@ -549,9 +922,11 @@ types: createdOn: type: optional docs: The date the collection was created + access: read-only lastUpdated: type: optional docs: The date the collection was last updated + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml CollectionList: @@ -561,12 +936,12 @@ types: docs: An array of Collections source: openapi: ../../../openapi/referenced-specs/v2.yml - FieldType: + StaticFieldType: enum: - Color - DateTime - Email - - ExtFileRef + - File - Image - Link - MultiImage @@ -575,31 +950,27 @@ types: - PlainText - RichText - Switch - - Video + - VideoLink docs: Choose these appropriate field type for your collection data inline: true source: openapi: ../../../openapi/referenced-specs/v2.yml - Field: - docs: The details of a field in a collection + Static Field: properties: id: - type: string + type: optional docs: Unique identifier for a Field - isRequired: - type: boolean - docs: define whether a field is required in a collection + access: read-only isEditable: type: optional docs: Define whether the field is editable + access: read-only + isRequired: + type: optional + docs: define whether a field is required in a collection type: - type: FieldType + type: StaticFieldType docs: Choose these appropriate field type for your collection data - slug: - type: optional - docs: >- - Slug of Field in Site URL structure. Slugs should be all lowercase - with no spaces. Any spaces will be converted to "-." displayName: type: string docs: The name of a field @@ -608,29 +979,216 @@ types: docs: Additional text to help anyone filling out this field source: openapi: ../../../openapi/referenced-specs/v2.yml - Collection: - docs: A collection object + MetadataOptionsItem: + docs: A single option value for the Option field. properties: - id: + name: type: string - docs: Unique identifier for a Collection - displayName: + docs: The name of the option + id: type: optional - docs: Name given to the Collection - singularName: + docs: The unique identifier of the option + access: read-only + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Metadata: + docs: The metadata for the Option field. + properties: + options: + docs: The option values for the Option field. + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Option Field: + properties: + id: type: optional - docs: >- - The name of one Item in Collection (e.g. ”Blog Post” if the Collection - is called “Blog Posts”) - slug: + docs: Unique identifier for a Field + access: read-only + isEditable: + type: optional + docs: Define whether the field is editable + access: read-only + isRequired: + type: optional + docs: define whether a field is required in a collection + type: + type: literal<"Option"> + docs: >- + The [Option field + type](/data/reference/field-types-item-values#option) + displayName: + type: string + docs: The name of a field + helpText: + type: optional + docs: Additional text to help anyone filling out this field + metadata: Metadata + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ReferenceFieldType: + enum: + - MultiReference + - Reference + docs: Choose these appropriate field type for your collection data + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + ReferenceFieldMetadata: + docs: >- + The collectionId for the referenced collection. Only applicable for + Reference and MultiReference fields. + properties: + collectionId: + type: string + docs: The unique identifier of the collection + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Reference Field: + properties: + id: + type: optional + docs: Unique identifier for a Field + access: read-only + isEditable: + type: optional + docs: Define whether the field is editable + access: read-only + isRequired: + type: optional + docs: define whether a field is required in a collection + type: + type: ReferenceFieldType + docs: Choose these appropriate field type for your collection data + displayName: + type: string + docs: The name of a field + helpText: + type: optional + docs: Additional text to help anyone filling out this field + metadata: + type: ReferenceFieldMetadata + docs: >- + The collectionId for the referenced collection. Only applicable for + Reference and MultiReference fields. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FieldCreate: + discriminated: false + docs: Details about the field of a collection + union: + - type: Static Field + - type: Option Field + - type: Reference Field + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FieldType: + enum: + - Color + - DateTime + - Email + - ExtFileRef + - File + - Image + - Link + - MultiImage + - MultiReference + - Number + - Option + - Phone + - PlainText + - Reference + - RichText + - Switch + - VideoLink + docs: Choose these appropriate field type for your collection data + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FieldValidationsAdditionalPropertiesAdditionalProperties: + properties: + additionalProperties: unknown + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + FieldValidationsAdditionalProperties: + discriminated: false + union: + - string + - double + - boolean + - integer + - FieldValidationsAdditionalPropertiesAdditionalProperties + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + FieldValidations: + docs: The validations for the field + properties: + additionalProperties: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Field: + docs: The details of a field in a collection + properties: + id: + type: string + docs: Unique identifier for a Field + isRequired: + type: boolean + docs: define whether a field is required in a collection + isEditable: + type: optional + docs: Define whether the field is editable + access: read-only + type: + type: FieldType + docs: Choose these appropriate field type for your collection data + slug: + type: optional + docs: >- + Slug of Field in Site URL structure. Slugs should be all lowercase + with no spaces. Any spaces will be converted to "-." + displayName: + type: string + docs: The name of a field + helpText: + type: optional + docs: Additional text to help anyone filling out this field + validations: + type: optional + docs: The validations for the field + access: read-only + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Collection: + docs: A collection object + properties: + id: + type: string + docs: Unique identifier for a Collection + displayName: + type: string + docs: Name given to the Collection + singularName: + type: string + docs: >- + The name of one Item in Collection (e.g. ”Blog Post” if the Collection + is called “Blog Posts”) + slug: type: optional docs: Slug of Collection in Site URL structure createdOn: type: optional docs: The date the collection was created + access: read-only lastUpdated: type: optional docs: The date the collection was last updated + access: read-only fields: docs: The list of fields in the Collection type: list @@ -669,18 +1227,22 @@ types: id: type: optional docs: Unique identifier for the Item + access: read-only cmsLocaleId: type: optional docs: Identifier for the locale of the CMS item lastPublished: type: optional docs: The date the item was last published + access: read-only lastUpdated: type: optional docs: The date the item was last updated + access: read-only createdOn: type: optional docs: The date the item was created + access: read-only isArchived: type: optional docs: Boolean determining if the Item is set to archived @@ -695,15 +1257,15 @@ types: CollectionItemListPagination: properties: limit: - type: optional + type: optional docs: The limit specified in the request default: 100 offset: - type: optional + type: optional docs: The offset specified for pagination default: 0 total: - type: optional + type: optional docs: Total number of items in the collection source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -750,18 +1312,22 @@ types: id: type: optional docs: Unique identifier for the Item + access: read-only cmsLocaleId: type: optional docs: Identifier for the locale of the CMS item lastPublished: type: optional docs: The date the item was last published + access: read-only lastUpdated: type: optional docs: The date the item was last updated + access: read-only createdOn: type: optional docs: The date the item was created + access: read-only isArchived: type: optional docs: Boolean determining if the Item is in an archived state. @@ -769,7 +1335,7 @@ types: isDraft: type: optional docs: Boolean determining if the Item is in a draft state. - default: false + default: true fieldData: CollectionItemPostSingleFieldData source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -803,12 +1369,15 @@ types: lastPublished: type: optional docs: The date the item was last published + access: read-only lastUpdated: type: optional docs: The date the item was last updated + access: read-only createdOn: type: optional docs: The date the item was created + access: read-only isArchived: type: optional docs: Boolean determining if the Item is set to archived @@ -826,6 +1395,7 @@ types: docs: List of Items within the collection source: openapi: ../../../openapi/referenced-specs/v2.yml + Conflict: unknown BulkCollectionItemFieldData: properties: name: @@ -848,7 +1418,7 @@ types: items properties: id: - type: string + type: optional docs: Unique identifier for the Item cmsLocaleIds: type: optional> @@ -856,12 +1426,15 @@ types: lastPublished: type: optional docs: The date the item was last published + access: read-only lastUpdated: type: optional docs: The date the item was last updated + access: read-only createdOn: type: optional docs: The date the item was created + access: read-only isArchived: type: optional docs: Boolean determining if the Item is set to archived @@ -897,18 +1470,22 @@ types: id: type: optional docs: Unique identifier for the Item + access: read-only cmsLocaleId: type: optional docs: Identifier for the locale of the CMS item lastPublished: type: optional docs: The date the item was last published + access: read-only lastUpdated: type: optional docs: The date the item was last updated + access: read-only createdOn: type: optional docs: The date the item was created + access: read-only isArchived: type: optional docs: Boolean determining if the Item is set to archived @@ -918,6 +1495,210 @@ types: fieldData: optional source: openapi: ../../../openapi/referenced-specs/v2.yml + CommentThreadAuthor: + properties: + userId: + type: string + docs: The unique identifier of the author + email: + type: string + docs: Email of the author + name: + type: string + docs: Name of the author + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentThreadMentionedUsersItem: + properties: + userId: + type: string + docs: The unique identifier of the mentioned user + email: + type: string + docs: Email of the user + name: + type: string + docs: Name of the User + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentThread: + docs: > + A comment thread represents a conversation between users on a specific + page. Each comment thread has a unique identifier and can contain multiple + comments. Retrieve comment replies using the replies API endpoint. + properties: + id: + type: string + docs: Unique identifier for the comment thread + siteId: + type: string + docs: The site unique identifier + pageId: + type: string + docs: The page unique identifier + localeId: + type: optional + docs: The locale unique identifier + access: read-only + itemId: + type: optional + docs: The item unique identifier + access: read-only + breakpoint: + type: string + docs: The breakpoint the comment was left on + url: + type: string + docs: The URL of the page the comment was left on + content: + type: string + docs: The content of the comment reply + isResolved: + type: boolean + docs: Boolean determining if the comment thread is resolved + default: false + author: CommentThreadAuthor + mentionedUsers: + docs: >- + List of mentioned users. This is an empty array until email + notifications are sent, which can take up to 5 minutes after the + comment is created. + type: list + createdOn: + type: string + docs: The date the item was created + lastUpdated: + type: string + docs: The date the item was last updated + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentThreadListPagination: + properties: + limit: + type: integer + docs: The limit specified in the request (default 100) + default: 100 + offset: + type: integer + docs: The offset specified for pagination + default: 0 + total: + type: integer + docs: Total number of comment threads + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentThreadList: + docs: > + A list of comment threads on the site. Contains the content of the first + reply. + properties: + comments: list + pagination: CommentThreadListPagination + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentReplyAuthor: + properties: + id: + type: string + docs: The unique identifier of the author + email: + type: string + docs: Email of the author + name: + type: string + docs: Name of the author + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentReplyMentionedUsersItem: + properties: + id: + type: string + docs: The unique identifier of the mentioned user + email: + type: string + docs: Email of the user + name: + type: string + docs: Name of the User + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentReply: + docs: > + A comment thread represents a conversation between users on a specific + page. Each comment thread has a unique identifier and can contain multiple + comments. + properties: + id: + type: string + docs: Unique identifier for the comment thread + commentId: + type: string + docs: The comment reply unique identifier + siteId: + type: string + docs: The site unique identifier + pageId: + type: string + docs: The page unique identifier + localeId: + type: optional + docs: The locale unique identifier + access: read-only + breakpoint: + type: string + docs: The breakpoint the comment was left on + content: + type: string + docs: The content of the comment reply + isResolved: + type: boolean + docs: Boolean determining if the comment thread is resolved + default: false + author: CommentReplyAuthor + mentionedUsers: + type: optional> + docs: >- + List of mentioned users is an empty array until email notifications + are sent. + lastUpdated: + type: optional + docs: The date the item was last updated + access: read-only + createdOn: + type: optional + docs: The date the item was created + access: read-only + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentReplyListPagination: + properties: + limit: + type: integer + docs: The limit specified in the request (default 100) + default: 100 + offset: + type: integer + docs: The offset specified for pagination + default: 0 + total: + type: integer + docs: Total number of comment replies + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentReplyList: + docs: | + A list of comment replies. + properties: + comments: list + pagination: CommentReplyListPagination + source: + openapi: ../../../openapi/referenced-specs/v2.yml PageSeo: docs: SEO-related fields for the Page properties: @@ -940,6 +1721,7 @@ types: type: optional docs: Indicates the Open Graph title was copied from the SEO title default: true + access: read-only description: type: optional docs: The description supplied to Open Graph annotations @@ -949,6 +1731,7 @@ types: Indicates the Open Graph description was copied from the SEO description default: true + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true @@ -961,6 +1744,7 @@ types: siteId: type: optional docs: Unique identifier for the Site + access: read-only title: type: optional docs: Title of the Page @@ -970,43 +1754,49 @@ types: parentId: type: optional docs: Identifier of the parent folder + access: read-only collectionId: type: optional docs: >- Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. + access: read-only createdOn: type: optional docs: The date the Page was created + access: read-only lastUpdated: type: optional docs: The date the Page was most recently updated + access: read-only archived: type: optional docs: Whether the Page has been archived default: false + access: read-only draft: type: optional docs: Whether the Page is a draft default: false + access: read-only canBranch: type: optional docs: >- Indicates whether the Page supports [Page - Branching](https://university.webflow.com/lesson/page-branching) + Branching](https://university.webflow.com/lesson/page-branching). + Pages that are already branches cannot be branched again. default: false + access: read-only isBranch: type: optional docs: >- Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) default: false - isMembersOnly: - type: optional - docs: >- - Indicates whether the Page is restricted by [Memberships - Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) - default: false + access: read-only + branchId: + type: optional + docs: If the Page is a Branch of another Page, this is the ID of the Branch seo: type: optional docs: SEO-related fields for the Page @@ -1016,9 +1806,11 @@ types: localeId: type: optional docs: Unique ID of the page locale + access: read-only publishedPath: type: optional docs: Relative path of the published page URL + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml PageList: @@ -1029,6 +1821,7 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml TextNodeText: + docs: The text content of the node properties: html: type: optional @@ -1046,15 +1839,18 @@ types: text for styling or other purposes. properties: id: - type: optional + type: string docs: Node UUID - text: optional + text: + type: TextNodeText + docs: The text content of the node attributes: type: optional> docs: The custom attributes of the node source: openapi: ../../../openapi/referenced-specs/v2.yml ImageNodeImage: + docs: The image details of the node properties: alt: optional assetId: optional @@ -1069,15 +1865,18 @@ types: can be associated with the image for styling or other purposes. properties: id: - type: optional + type: string docs: Node UUID - image: optional + image: + type: ImageNodeImage + docs: The image details of the node attributes: type: optional> docs: The custom attributes of the node source: openapi: ../../../openapi/referenced-specs/v2.yml Text: + docs: The text content of the node properties: html: type: optional @@ -1128,14 +1927,96 @@ types: the component instance, such as its type and properties. properties: id: - type: optional - docs: Node UUID + type: string + docs: The unique identifier of the component instance node componentId: - type: optional - docs: Component ID + type: string + docs: The unique identifier of the component propertyOverrides: - type: optional> docs: List of component properties with overrides for a component instance. + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml + TextInputNode: + docs: > + Represents text input and textarea elements within the DOM. It contains + the placeholder text in the input. Additional attributes can be associated + with the text for styling or other purposes. + properties: + id: + type: string + docs: Node UUID + placeholder: + type: string + docs: The placeholder text of the input node + attributes: + type: optional> + docs: The custom attributes of the node + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SelectNodeChoicesItem: + properties: + value: + type: string + docs: The value of the choice when selected. + text: + type: string + docs: The text to display for the choice. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + SelectNode: + docs: > + Represents select elements within the DOM. It contains the list of choices + in the select. Additional attributes can be associated with the text for + styling or other purposes. + properties: + id: + type: string + docs: Node UUID + choices: + docs: The list of choices in this select node. + type: list + attributes: + type: optional> + docs: The custom attributes of the node + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SubmitButtonNode: + docs: > + Represents submit button elements within the DOM. It contains the text and + waiting text of the button. Additional attributes can be associated with + the text for styling or other purposes. + properties: + id: + type: string + docs: Node UUID + value: + type: string + docs: The text content of the submit button. + waitingText: + type: string + docs: The text to show while the form is submitting. + attributes: + type: optional> + docs: The custom attributes of the node + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SearchButtonNode: + docs: > + Represents search button elements within the DOM. It contains the text of + the button. Additional attributes can be associated with the text for + styling or other purposes. + properties: + id: + type: string + docs: Node UUID + value: + type: string + docs: The text content of the search button. + attributes: + type: optional> + docs: The custom attributes of the node source: openapi: ../../../openapi/referenced-specs/v2.yml Node: @@ -1146,9 +2027,20 @@ types: Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. union: - text: TextNode - image: ImageNode - component-instance: ComponentNode + text: + type: TextNode + image: + type: ImageNode + component-instance: + type: ComponentNode + text-input: + type: TextInputNode + select: + type: SelectNode + submit-button: + type: SubmitButtonNode + search-button: + type: SearchButtonNode source: openapi: ../../../openapi/referenced-specs/v2.yml Dom: @@ -1163,8 +2055,17 @@ types: pageId: type: optional docs: Page ID + branchId: + type: optional + docs: >- + The unique identifier of a [specific page + branch.](https://help.webflow.com/hc/en-us/articles/33961355506195-Page-branching) nodes: optional> pagination: optional + lastUpdated: + type: optional + docs: The date the page dom was most recently updated + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml TextNodeWrite: @@ -1214,6 +2115,64 @@ types: type: list source: openapi: ../../../openapi/referenced-specs/v2.yml + SelectNodeWriteChoicesItem: + properties: + value: + type: string + docs: The value of the choice when selected. + text: + type: string + docs: The text to display for the choice. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Select: + docs: Update choices on a select node + properties: + nodeId: + type: string + docs: Node UUID + choices: + docs: The list of choices to set on the select node. + type: list + source: + openapi: ../../../openapi/referenced-specs/v2.yml + TextInputNodeWrite: + docs: Update placeholder text on a text input node + properties: + nodeId: + type: string + docs: Node UUID + placeholder: + type: string + docs: The placeholder text of the input node + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SubmitButtonNodeWrite: + docs: Update a submit button node + properties: + nodeId: + type: string + docs: Node UUID + value: + type: optional + docs: The text content of the submit button. + waitingText: + type: optional + docs: The text to show while the form is submitting. + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SearchButtonNodeWrite: + docs: Update a search button node + properties: + nodeId: + type: string + docs: Node UUID + value: + type: string + docs: The text content of the search button. + source: + openapi: ../../../openapi/referenced-specs/v2.yml Component: docs: The Component object properties: @@ -1223,18 +2182,22 @@ types: name: type: optional docs: Component Name + access: read-only group: type: optional docs: The group that the component belongs to + access: read-only description: type: optional docs: Component Description + access: read-only readonly: type: optional docs: >- Indicates whether the component is read-only. Components that cannot be updated within this Site are set to readonly. Workspace Libraries are a good example. + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml ComponentList: @@ -1249,8 +2212,8 @@ types: The Component DOM schema represents the content structure of a component. Similar to Page DOM, it captures various content nodes and their associated attributes, but specifically for a component's structure. Each - node has a unique identifier and can contain text, images, or nested - component instances. + node has a unique identifier and can contain text, images, select or text + inputs, submit buttons, or nested component instances. properties: componentId: type: optional @@ -1270,6 +2233,7 @@ types: componentId: type: optional docs: Component ID + access: read-only properties: optional> pagination: optional source: @@ -1314,9 +2278,11 @@ types: lastUpdated: type: optional docs: Date when the Site's scripts were last updated + access: read-only createdOn: type: optional docs: Date when the Site's scripts were created + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml CustomCodeHostedResponse: @@ -1325,6 +2291,7 @@ types: id: type: optional docs: Human readable id, derived from the user-specified display name + access: read-only canCopy: type: optional docs: >- @@ -1347,9 +2314,11 @@ types: createdOn: type: optional docs: Timestamp when the script version was created + access: read-only lastUpdated: type: optional docs: Timestamp when the script version was last updated + access: read-only version: type: optional docs: A Semantic Version (SemVer) string, denoting the version of the script @@ -1359,6 +2328,7 @@ types: docs: A list of scripts registered to the site properties: registeredScripts: optional> + pagination: optional source: openapi: ../../../openapi/referenced-specs/v2.yml CustomCodeInlineResponse: @@ -1367,6 +2337,7 @@ types: id: type: optional docs: Human readable id, derived from the user-specified display name + access: read-only canCopy: type: optional docs: >- @@ -1389,9 +2360,11 @@ types: createdOn: type: optional docs: Timestamp when the script version was created + access: read-only lastUpdated: type: optional docs: Timestamp when the script version was last updated + access: read-only version: type: optional docs: A Semantic Version (SemVer) string, denoting the version of the script @@ -1426,9 +2399,11 @@ types: createdOn: type: optional docs: The date the Block was created + access: read-only lastUpdated: type: optional docs: The date the Block was most recently updated + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml ListCustomCodeBlocks: @@ -1439,29 +2414,30 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml AssetVariant: + docs: Asset variant details properties: hostedUrl: - type: optional + type: string docs: URL of where the asset variant is hosted validation: format: uri originalFileName: - type: optional + type: string docs: Original file name of the variant displayName: - type: optional + type: string docs: Display name of the variant format: - type: optional + type: string docs: format of the variant width: - type: optional + type: integer docs: Width in pixels height: type: optional docs: Height in pixels quality: - type: optional + type: integer docs: Value between 0 and 100 representing the image quality error: type: optional @@ -1469,37 +2445,51 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml Asset: + docs: Asset details properties: id: type: optional docs: Unique identifier for this asset + access: read-only contentType: type: optional docs: File format type + access: read-only size: type: optional docs: size in bytes + access: read-only siteId: type: optional docs: Unique identifier for the site that hosts this asset + access: read-only hostedUrl: type: optional docs: Link to the asset validation: format: uri + access: read-only originalFileName: type: optional docs: Original file name at the time of upload + access: read-only displayName: - type: optional + type: string docs: Display name of the asset lastUpdated: type: optional docs: Date the asset metadata was last updated + access: read-only createdOn: type: optional docs: Date the asset metadata was created - variants: optional> + access: read-only + variants: + docs: >- + A list of [asset + variants](https://help.webflow.com/hc/en-us/articles/33961378697107-Responsive-images) + created by Webflow to serve your site responsively. + type: list altText: type: optional docs: The visual description of the asset @@ -1509,6 +2499,7 @@ types: docs: A list of assets properties: assets: optional> + pagination: optional source: openapi: ../../../openapi/referenced-specs/v2.yml AssetUploadUploadDetails: @@ -1610,54 +2601,15 @@ types: - ecomm_new_order - ecomm_order_changed - ecomm_inventory_changed - - user_account_added - - user_account_updated - - user_account_deleted - collection_item_created - collection_item_changed - collection_item_deleted + - collection_item_published - collection_item_unpublished + - comment_created docs: > - * `form_submission` - Sends the [form_submission](#form_submission) event - - * `site_publish` - Sends a [site_publish](#site_publish) event - - * `page_created` - Send the [page_created](#page_created) event - - * `page_metadata_updated` - Sends the - [page_metadata_updated](#page_metadata_updated) event - - * `page_deleted` - Sends the [page_deleted](#page_deleted) event - - * `ecomm_new_order` - Sends the new [ecomm_new_order](#ecomm_new_order) - event - - * `ecomm_order_changed` - Sends the - [ecomm_order_changed](#ecomm_order_changed) event - - * `ecomm_inventory_changed` - Sends the - [ecomm_inventory_changed](#ecomm_inventory_changed) event - - * `user_account_added` - Sends the - [user_account_added](#user_account_added) event - - * `user_account_updated` - Sends the - [user_account_updated](#user_account_updated) event - - * `user_account_deleted` - Sends the - [user_account_deleted](#user_account_deleted) event - - * `collection_item_created` - Sends the - [collection_item_created](#collection_item_created) event - - * `collection_item_changed` - Sends the - [collection_item_changed](#collection_item_changed) event - - * `collection_item_deleted` - Sends the - [collection_item_deleted](#collection_item_deleted) event - - * `collection_item_unpublished` - Sends the - [collection_item_unpublished](#collection_item_unpublished) event + The type of event that triggered the request. See the the documentation + for details on [supported events](/data/reference/all-events). source: openapi: ../../../openapi/referenced-specs/v2.yml WebhookFilter: @@ -1676,6 +2628,7 @@ types: id: type: optional docs: Unique identifier for the Webhook registration + access: read-only triggerType: optional url: type: optional @@ -1683,9 +2636,11 @@ types: workspaceId: type: optional docs: Unique identifier for the Workspace the Webhook is registered in + access: read-only siteId: type: optional docs: Unique identifier for the Site the Webhook is registered in + access: read-only filter: type: optional docs: >- @@ -1694,15 +2649,17 @@ types: lastTriggered: type: optional docs: Date the Webhook instance was last triggered + access: read-only createdOn: type: optional docs: Date the Webhook registration was created + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml WebhookList: properties: - pagination: optional webhooks: optional> + pagination: optional source: openapi: ../../../openapi/referenced-specs/v2.yml FormFieldValueType: @@ -1830,175 +2787,6 @@ types: pagination: optional source: openapi: ../../../openapi/referenced-specs/v2.yml - UserDataData: - properties: - name: - type: optional - docs: | - The name of the user - email: - type: optional - docs: | - The email address of the user - accept-privacy: - type: optional - docs: | - Boolean indicating if the user has accepted the privacy policy - accept-communications: - type: optional - docs: | - Boolean indicating if the user has accepted to receive communications - additionalProperties: - type: optional - docs: Custom user attributes - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - UserData: - docs: An object containing the User's basic info and custom fields - properties: - data: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - UserStatus: - enum: - - invited - - verified - - unverified - docs: The status of the user - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - UserAccessGroupsItemType: - enum: - - admin - - ecommerce - docs: | - The type of access group based on how it was assigned to the user. - * `admin` - Assigned to the user via API or in the designer - * `ecommerce` - Assigned to the user via an ecommerce purchase - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - UserAccessGroupsItem: - docs: Access group slugs and types - properties: - slug: - type: optional - docs: Access group identifier for APIs - type: - type: optional - docs: | - The type of access group based on how it was assigned to the user. - * `admin` - Assigned to the user via API or in the designer - * `ecommerce` - Assigned to the user via an ecommerce purchase - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - User: - docs: > - The fields that define the schema for a given Item are based on the - Collection that Item belongs to. Beyond the user defined fields, there are - a handful of additional fields that are automatically created for all - items - properties: - id: - type: optional - docs: Unique identifier for the User - isEmailVerified: - type: optional - docs: Shows whether the user has verified their email address - lastUpdated: - type: optional - docs: The timestamp the user was updated - invitedOn: - type: optional - docs: The timestamp the user was invited - createdOn: - type: optional - docs: The timestamp the user was created - lastLogin: - type: optional - docs: The timestamp the user was logged in - status: - type: optional - docs: The status of the user - accessGroups: - type: optional> - docs: Access groups the user belongs to - data: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - UserList: - docs: The list users results - properties: - count: - type: optional - docs: Number of users returned - limit: - type: optional - docs: The limit specified in the request - default: 10 - offset: - type: optional - docs: The offset specified for pagination - default: 0 - total: - type: optional - docs: Total number of users in the collection - users: - type: optional> - docs: List of Users for a Site - source: - openapi: ../../../openapi/referenced-specs/v2.yml - UsersNotEnabled: unknown - DuplicateUserEmail: unknown - UserLimitReached: unknown - AccessGroup: - properties: - id: - type: optional - docs: Unique identifier for the Access Group - name: - type: optional - docs: Name of the the Access Group - shortId: - type: optional - docs: >- - Shortened unique identifier based on name, optimized for its use in - the user’s JWT - slug: - type: optional - docs: >- - Shortened unique identifier based on name, optimized for human - readability and public API use - createdOn: - type: optional - docs: The date the Access Group was created - source: - openapi: ../../../openapi/referenced-specs/v2.yml - AccessGroupList: - docs: The list access groups results - properties: - count: - type: optional - docs: Number of access groups returned - limit: - type: optional - docs: The limit specified in the request - default: 10 - offset: - type: optional - docs: The offset specified for pagination - default: 0 - total: - type: optional - docs: Total number of access groups in the collection - accessGroups: - type: optional> - docs: List of Site Access Groups - source: - openapi: ../../../openapi/referenced-specs/v2.yml SkuPropertyListEnumItem: docs: Enumerated Product variants/Options for the SKU properties: @@ -2128,9 +2916,9 @@ types: sku-properties: type: optional> docs: Variant types to include in SKUs - categories: + category: type: optional> - docs: The categories your product belongs to. + docs: The category your product belongs to. tax-category: type: optional docs: Product tax class @@ -2152,18 +2940,23 @@ types: id: type: optional docs: Unique identifier for the Product + access: read-only cmsLocaleId: type: optional docs: Identifier for the locale of the CMS item + access: read-only lastPublished: type: optional docs: The date the Product was last published + access: read-only lastUpdated: type: optional docs: The date the Product was last updated + access: read-only createdOn: type: optional docs: The date the Product was created + access: read-only isArchived: type: optional docs: Boolean determining if the Product is set to archived @@ -2178,8 +2971,10 @@ types: SkuValueList: type: map docs: > - A dictionary that maps a SKU property to a SKU value. The key of the - dictionary is the SKU property ID, and the value is the SKU value ID. + A mapping between SKU properties and their values, represented as + key-value pairs. Each key represents a SKU Property ID (e.g. "color") and + maps to its corresponding SKU Value ID (e.g. "blue"). This structure + defines the specific variant combination for a SKU. SkuFieldDataPrice: docs: price of SKU properties: @@ -2189,6 +2984,9 @@ types: unit: type: optional docs: Currency of Item + currency: + type: optional + docs: Currency of Item (alternative representation) source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true @@ -2209,6 +3007,10 @@ types: - value: one-time name: OneTime - subscription + docs: >- + [Billing + method](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#billing-methods)for + the SKU inline: true source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -2246,6 +3048,10 @@ types: openapi: ../../../openapi/referenced-specs/v2.yml inline: true SkuFieldDataEcSkuSubscriptionPlan: + docs: >- + [Subscription + plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) + for the SKU properties: interval: type: optional @@ -2256,7 +3062,9 @@ types: trial: type: optional docs: Number of days of a trial - plans: optional> + plans: + type: optional> + access: read-only source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true @@ -2276,17 +3084,27 @@ types: compare-at-price: type: optional docs: comparison price of SKU - ec-sku-billing-method: optional - ec-sku-subscription-plan: optional - track-inventory: - type: optional + ec-sku-billing-method: + type: optional docs: >- - A boolean indicating whether inventory for this product should be - tracked. - default: false - quantity: - type: optional - docs: Quantity of SKU that will be tracked as items are ordered. + [Billing + method](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#billing-methods)for + the SKU + ec-sku-subscription-plan: + type: optional + docs: >- + [Subscription + plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) + for the SKU + main-image: + type: optional + docs: The URL for the main image of the SKU + sku: + type: optional + docs: A unique identifier for the SKU + sku-properties: + type: optional> + docs: The properties of the SKU source: openapi: ../../../openapi/referenced-specs/v2.yml Sku: @@ -2295,18 +3113,23 @@ types: id: type: optional docs: Unique identifier for the Product + access: read-only cmsLocaleId: type: optional docs: Identifier for the locale of the CMS item + access: read-only lastPublished: type: optional docs: The date the Product was last published + access: read-only lastUpdated: type: optional docs: The date the Product was last updated + access: read-only createdOn: type: optional docs: The date the Product was created + access: read-only fieldData: optional source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -2472,6 +3295,7 @@ types: productId: type: optional docs: The unique identifier for the Product + access: read-only productName: type: optional docs: User-facing name of the Product @@ -2637,9 +3461,115 @@ types: inline: true source: openapi: ../../../openapi/referenced-specs/v2.yml - OrderCustomerInfo: - docs: An object with the keys `fullName` and `email`. - properties: + OrderShippingAddressType: + enum: + - shipping + - billing + docs: The type of the order address (billing or shipping) + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderShippingAddressJapanType: + enum: + - kana + - kanji + docs: >- + Represents a Japan-only address format. This field will only appear on + orders placed from Japan. + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderShippingAddress: + docs: The shipping address + properties: + type: + type: optional + docs: The type of the order address (billing or shipping) + japanType: + type: optional + docs: >- + Represents a Japan-only address format. This field will only appear on + orders placed from Japan. + addressee: + type: optional + docs: Display name on the address + line1: + type: optional + docs: The first line of the address + line2: + type: optional + docs: The second line of the address + city: + type: optional + docs: The city of the address. + state: + type: optional + docs: The state or province of the address + country: + type: optional + docs: The country of the address + postalCode: + type: optional + docs: The postal code of the address + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + OrderBillingAddressType: + enum: + - shipping + - billing + docs: The type of the order address (billing or shipping) + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderBillingAddressJapanType: + enum: + - kana + - kanji + docs: >- + Represents a Japan-only address format. This field will only appear on + orders placed from Japan. + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + OrderBillingAddress: + docs: The billing address + properties: + type: + type: optional + docs: The type of the order address (billing or shipping) + japanType: + type: optional + docs: >- + Represents a Japan-only address format. This field will only appear on + orders placed from Japan. + addressee: + type: optional + docs: Display name on the address + line1: + type: optional + docs: The first line of the address + line2: + type: optional + docs: The second line of the address + city: + type: optional + docs: The city of the address. + state: + type: optional + docs: The state or province of the address + country: + type: optional + docs: The country of the address + postalCode: + type: optional + docs: The postal code of the address + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + OrderCustomerInfo: + docs: An object with the keys `fullName` and `email`. + properties: fullName: type: optional docs: The full name of the Customer @@ -2725,6 +3655,7 @@ types: The order ID. Will usually be 6 hex characters, but can also be 9 hex characters if the site has a very large number of Orders. Randomly assigned. + access: read-only status: type: optional docs: | @@ -2780,10 +3711,10 @@ types: type: optional> docs: All addresses provided by the customer during the ordering flow. shippingAddress: - type: optional + type: optional docs: The shipping address billingAddress: - type: optional + type: optional docs: The billing address shippingProvider: type: optional @@ -2868,6 +3799,7 @@ types: id: type: optional docs: Unique identifier for a SKU item + access: read-only quantity: type: optional docs: >- @@ -2884,11 +3816,496 @@ types: siteId: type: optional docs: The identifier of the Site + access: read-only createdOn: type: optional docs: Date that the Site was created on + access: read-only defaultCurrency: type: optional docs: The three-letter ISO currency code for the Site source: openapi: ../../../openapi/referenced-specs/v2.yml + FormSubmissionTriggerPayloadSchemaItemFieldType: + enum: + - FormTextInput + - FormTextarea + - FormCheckboxInput + - FormRadioInput + - FormFileUploadInput + docs: Form field type + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + FormSubmissionTriggerPayloadSchemaItem: + properties: + fieldName: + type: optional + docs: Form field name + fieldType: + type: optional + docs: Form field type + fieldElementId: + type: optional + docs: Element ID of the Form Field + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + FormSubmissionTriggerPayload: + docs: The payload of data sent from Webflow + properties: + name: + type: optional + docs: The name of the form + siteId: + type: optional + docs: The ID of the site that the form was submitted from + data: + type: optional> + docs: The data submitted in the form + schema: + type: optional> + docs: A list of fields from the submitted form + submittedAt: + type: optional + docs: The timestamp the form was submitted + id: + type: optional + docs: the ID of the event + formId: + type: optional + docs: The ID of the form submission + formElementId: + type: optional + docs: The uniqueID of the Form element + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + FormSubmissionTrigger: + docs: The Webhook payload for when a form is submitted + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SitePublishPayload: + docs: The payload of data sent from Webflow + properties: + siteId: + type: optional + docs: The ID of the site that was published + publishedOn: + type: optional + docs: The timestamp of the publish event + domains: + type: optional> + docs: The domains that were published + publishedBy: + type: optional> + docs: The name andID of the user who published the site + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + SitePublish: + docs: The Webhook payload for when a Site is published + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + NewOrder: + docs: The Webhook payload for when a new order is created + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + UpdatedOrder: + docs: The Webhook payload for when an order is updated + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + SingleLocaleCreatedPayloadFieldData: + properties: + name: string + slug: string + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + SingleLocaleCreatedPayload: + properties: + id: + type: string + docs: Unique identifier for the Item + validation: + format: uuid + workspaceId: + type: string + docs: Unique identifier of the workspace + validation: + format: uuid + siteId: + type: string + docs: Unique identifier of the site + validation: + format: uuid + collectionId: + type: string + docs: Unique identifier of the collection + validation: + format: uuid + cmsLocaleId: + type: optional + docs: Unique identifier of the CMS locale for this item + validation: + format: uuid + lastPublished: optional + lastUpdated: optional + createdOn: optional + isArchived: optional + isDraft: optional + fieldData: SingleLocaleCreatedPayloadFieldData + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemCreated: + docs: The Webhook payload for when a Collection Item is created + properties: + triggerType: + type: literal<"collection_item_created"> + docs: The type of event that triggered the request + payload: + type: SingleLocaleCreatedPayload + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemChanged: + docs: The Webhook payload for when a Collection Item is changed + properties: + triggerType: + type: literal<"collection_item_changed"> + docs: The type of event that triggered the request + payload: + type: SingleLocaleCreatedPayload + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemRemovedPayloadFieldData: + properties: + name: string + slug: string + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemRemovedPayload: + docs: The payload of data sent from Webflow + properties: + id: + type: optional + docs: The ID of the collection item that was deleted + siteId: + type: optional + docs: The ID of the site + workspaceId: + type: optional + docs: The ID of the workspace + collectionId: + type: optional + docs: The ID of the collection + cmsLocaleId: + type: optional + docs: Unique identifier of the CMS locale for this item + validation: + format: uuid + lastPublished: optional + lastUpdated: optional + createdOn: optional + isArchived: optional + isDraft: optional + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemRemoved: + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PayloadFieldData: + properties: + name: string + slug: string + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Payload: + docs: The payload of data sent from Webflow + properties: + id: + type: optional + docs: The ID of the collection item that was unpublished + siteId: + type: optional + docs: The ID of the site + workspaceId: + type: optional + docs: The ID of the workspace + collectionId: + type: optional + docs: The ID of the collection + cmsLocaleId: + type: optional + docs: Unique identifier of the CMS locale for this item + validation: + format: uuid + lastPublished: optional + lastUpdated: optional + createdOn: optional + isArchived: optional + isDraft: optional + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemPublished: + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CollectionItemUnpublishedPayloadFieldData: + properties: + name: string + slug: string + extra-properties: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemUnpublishedPayload: + docs: The payload of data sent from Webflow + properties: + id: + type: optional + docs: The ID of the collection item that was unpublished + siteId: + type: optional + docs: The ID of the site + workspaceId: + type: optional + docs: The ID of the workspace + collectionId: + type: optional + docs: The ID of the collection + cmsLocaleId: + type: optional + docs: Unique identifier of the CMS locale for this item + validation: + format: uuid + lastPublished: optional + lastUpdated: optional + createdOn: optional + isArchived: optional + isDraft: optional + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CollectionItemUnpublished: + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PageCreatedWebhookPayload: + docs: The payload of data sent from Webflow + properties: + siteId: optional + pageId: optional + pageTitle: optional + createdOn: optional + publishedPath: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + PageCreatedWebhook: + docs: The Webhook payload for when a Page is created + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PageMetadataUpdatedWebhookPayload: + docs: The payload of data sent from Webflow + properties: + siteId: optional + pageId: optional + pageTitle: optional + lastUpdated: optional + publishedPath: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + PageMetadataUpdatedWebhook: + docs: The Webhook payload for when a Page's metadata is updated + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + PageDeletedWebhookPayload: + docs: The payload of data sent from Webflow + properties: + siteId: optional + pageId: optional + pageTitle: optional + deletedOn: optional + publishedPath: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + PageDeletedWebhook: + docs: The Webhook payload for when a Page is deleted + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: + type: optional + docs: The payload of data sent from Webflow + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentPayloadAuthor: + properties: + userId: + type: string + docs: The unique identifier of the author + email: + type: string + docs: Email of the author + name: + type: string + docs: Name of the author + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentPayloadMentionedUsersItem: + properties: + userId: + type: string + docs: The unique identifier of the mentioned user + email: + type: string + docs: Email of the user + name: + type: string + docs: Name of the User + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + CommentPayload: + docs: > + The comment webhook payload contains data for the thread and for replies. + Check the type to determine if the payload is for a thread or a reply. + The webhook payload may be delayed by up to 5 minutes. + properties: + threadId: + type: optional + docs: Unique identifier for the comment thread + access: read-only + commentId: + type: optional + docs: Unique identifier for the comment reply + access: read-only + type: + type: optional + docs: The type of comment payload + access: read-only + siteId: + type: optional + docs: The site unique identifier + access: read-only + pageId: + type: optional + docs: The page unique identifier + access: read-only + localeId: + type: optional + docs: The locale unique identifier + access: read-only + itemId: + type: optional + docs: The item unique identifier + access: read-only + breakpoint: + type: optional + docs: The breakpoint the comment was left on + access: read-only + url: + type: optional + docs: The URL of the page the comment was left on + access: read-only + content: + type: string + docs: The content of the comment reply + isResolved: + type: boolean + docs: Boolean determining if the comment thread is resolved + default: false + author: CommentPayloadAuthor + mentionedUsers: + docs: >- + List of mentioned users. This is an empty array until email + notifications are sent, which can take up to 5 minutes after the + comment is created. + type: list + createdOn: + type: optional + docs: The date the item was created + access: read-only + lastUpdated: + type: optional + docs: The date the item was last updated + access: read-only + source: + openapi: ../../../openapi/referenced-specs/v2.yml + Comment: + docs: The Webhook payload for when a comment thread or reply is made on a Site + properties: + triggerType: + type: optional + docs: The type of event that triggered the request + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/accessGroups.yml b/.mock/definition/accessGroups.yml deleted file mode 100644 index d8828f8..0000000 --- a/.mock/definition/accessGroups.yml +++ /dev/null @@ -1,80 +0,0 @@ -types: - AccessGroupsListRequestSort: - enum: - - value: CreatedOn - name: CreatedOnAscending - docs: Sorts users in ascending order based on their created date - - value: '-CreatedOn' - name: CreatedOnDescending - docs: Sorts users in descending order based on their created date - source: - openapi: ../../../openapi/referenced-specs/v2.yml -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/accessgroups - method: GET - auth: true - docs: | - Get a list of access groups for a site - - Required scope | `users:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Access Groups - request: - name: AccessGroupsListRequest - query-parameters: - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - sort: - type: optional - docs: | - Sort string to use when ordering access groups - Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) - response: - docs: Request was successful - type: root.AccessGroupList - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - count: 1 - limit: 10 - offset: 0 - total: 1 - accessGroups: - - id: 62be58d404be8a6cc900c081 - name: Research Team - shortId: rt - slug: hitchhikers-guide-research-team - createdOn: '2022-08-01T19:41:48Z' - - id: 65a96161991e77bbb4a6c573 - name: Admin - shortId: ad - slug: admin - createdOn: '2022-08-01T19:41:48Z' - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/api.yml b/.mock/definition/api.yml index aee9acd..de74f2d 100644 --- a/.mock/definition/api.yml +++ b/.mock/definition/api.yml @@ -3,8 +3,13 @@ error-discrimination: strategy: status-code display-name: Data API environments: - Default: https://api.webflow.com/v2 -default-environment: Default + Data API: + urls: + Base: https://api.webflow.com/v2 + Data API: https://api.webflow.com/v2 + Content Delivery API: https://api-cdn.webflow.com/v2 +default-environment: Data API +default-url: Base auth-schemes: BearerToken: scheme: bearer diff --git a/.mock/definition/assets.yml b/.mock/definition/assets.yml index 35392ec..dcdff94 100644 --- a/.mock/definition/assets.yml +++ b/.mock/definition/assets.yml @@ -7,9 +7,11 @@ service: list: path: /sites/{site_id}/assets method: GET - auth: true + auth: + - OAuth2: + - assets:read docs: | - List assets for a given site + List of assets uploaded to a site Required scope | `assets:read` source: @@ -19,9 +21,21 @@ service: type: string docs: Unique identifier for a Site display-name: List Assets + request: + name: AssetsListRequest + query-parameters: + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' response: docs: Request was successful type: root.Assets + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -31,6 +45,9 @@ service: examples: - path-parameters: site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + offset: 1 + limit: 1 response: body: assets: @@ -55,35 +72,66 @@ service: width: 500 height: 900 quality: 100 - altText: A red chair + altText: A single candy wrapper + - id: 63e5889e7fe4eafa7384cea5 + contentType: image/png + size: 2212772 + siteId: 63938b302ea6b0aa6f3d8745 + hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg + originalFileName: Gum-Wrapper.svg + displayName: 63e5889e7fe4eafa7384cea5_Gum-Wrapper.png + lastUpdated: '2023-03-01T23:42:57Z' + createdOn: '2023-02-09T23:58:22Z' + variants: + - hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + originalFileName: >- + Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + displayName: >- + 660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + format: png + width: 500 + height: 900 + quality: 100 + altText: A single gum wrapper + pagination: + limit: 2 + offset: 0 + total: 2 create: path: /sites/{site_id}/assets method: POST - auth: true + auth: + - OAuth2: + - assets:write docs: > - Create a new asset entry. + The first step in uploading an asset to a site. This endpoint generates a response with the following information: - `uploadUrl` and `uploadDetails`. + `uploadUrl` and `uploadDetails`. - You can use these two properties to [upload the file to Amazon s3 by - making a - POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) - request to the `uploadUrl` with the `uploadDetails` object as your - header information in the request. - - Required scope | `assets:write` + Use these properties in the header of a [POST request to Amazson + s3](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) + to complete the upload. + + + + To learn more about how to upload assets to Webflow, see our [assets + guide](/data/docs/working-with-assets). + + Required scope | `assets:write` source: openapi: ../../../openapi/referenced-specs/v2.yml path-parameters: site_id: type: string docs: Unique identifier for a Site - display-name: Create Asset Metadata + display-name: Upload Asset request: name: AssetsCreateRequest body: @@ -103,6 +151,7 @@ service: response: docs: Request was successful type: root.AssetUpload + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -137,16 +186,18 @@ service: assetUrl: >- https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d907ab9e91e3e9f56385e_paranoidAndroid-2024.png hostedUrl: >- - https://d1otoma47x30pg.cloudfront.net/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png + https://dev-assets.website-files.com/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png originalFileName: file.png createdOn: '2023-04-11T16:32:21Z' lastUpdated: '2023-04-12T20:31:03Z' get: path: /assets/{asset_id} method: GET - auth: true + auth: + - OAuth2: + - assets:read docs: | - Get an Asset + Get details about an asset Required scope | `assets:read` source: @@ -159,6 +210,7 @@ service: response: docs: Request was successful type: root.Asset + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -170,29 +222,34 @@ service: asset_id: 580e63fc8c9a982ac9b8b745 response: body: - id: 55131cd036c09f7d07883dfc + id: 63e5889e7fe4eafa7384cea4 contentType: image/png - size: 1500 - siteId: 62749158efef318abc8d5a0f - hostedUrl: example.com/hostedimage.png - originalFileName: image.png - displayName: example-image-123.png - lastUpdated: '2016-09-06T21:12:22Z' - createdOn: '2016-09-02T23:26:22Z' + size: 2212772 + siteId: 63938b302ea6b0aa6f3d8745 + hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg + originalFileName: Candy-Wrapper.svg + displayName: 63e5889e7fe4eafa7384cea4_Candy-Wrapper.png + lastUpdated: '2023-03-01T23:42:57Z' + createdOn: '2023-02-09T23:58:22Z' variants: - - hostedUrl: example.com/hostedimage.png - originalFileName: image.png - displayName: A brown dog - format: format - width: 1500 + - hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + originalFileName: Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + displayName: >- + 660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + format: png + width: 500 height: 900 - quality: 1 + quality: 100 error: error - altText: A red chair + altText: A single candy wrapper delete: path: /assets/{asset_id} method: DELETE - auth: true + auth: + - OAuth2: + - assets:write docs: | Delete an Asset @@ -216,9 +273,11 @@ service: update: path: /assets/{asset_id} method: PATCH - auth: true + auth: + - OAuth2: + - assets:write docs: | - Update an Asset + Update details of an Asset. Required scope | `assets:write` source: @@ -244,6 +303,7 @@ service: response: docs: Request was successful type: root.Asset + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -256,29 +316,34 @@ service: request: {} response: body: - id: 55131cd036c09f7d07883dfc + id: 63e5889e7fe4eafa7384cea4 contentType: image/png - size: 1500 - siteId: 62749158efef318abc8d5a0f - hostedUrl: example.com/hostedimage.png - originalFileName: image.png - displayName: example-image-123.png - lastUpdated: '2016-09-06T21:12:22Z' - createdOn: '2016-09-02T23:26:22Z' + size: 2212772 + siteId: 63938b302ea6b0aa6f3d8745 + hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg + originalFileName: Candy-Wrapper.svg + displayName: 63e5889e7fe4eafa7384cea4_Candy-Wrapper.png + lastUpdated: '2023-03-01T23:42:57Z' + createdOn: '2023-02-09T23:58:22Z' variants: - - hostedUrl: example.com/hostedimage.png - originalFileName: image.png - displayName: A brown dog - format: format - width: 1500 + - hostedUrl: >- + https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + originalFileName: Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + displayName: >- + 660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png + format: png + width: 500 height: 900 - quality: 1 + quality: 100 error: error - altText: A red chair + altText: A single candy wrapper list-folders: path: /sites/{site_id}/asset_folders method: GET - auth: true + auth: + - OAuth2: + - assets:read docs: | List Asset Folders within a given site @@ -293,6 +358,7 @@ service: response: docs: Request was successful type: root.AssetFolderList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -321,7 +387,9 @@ service: create-folder: path: /sites/{site_id}/asset_folders method: POST - auth: true + auth: + - OAuth2: + - assets:write docs: | Create an Asset Folder within a given site @@ -349,6 +417,7 @@ service: response: docs: Request was successful type: root.AssetFolder + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -374,7 +443,9 @@ service: get-folder: path: /asset_folders/{asset_folder_id} method: GET - auth: true + auth: + - OAuth2: + - assets:read docs: | Get details about a specific Asset Folder @@ -389,6 +460,7 @@ service: response: docs: Request was successful type: root.AssetFolder + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError diff --git a/.mock/definition/collections.yml b/.mock/definition/collections.yml index 661b54b..b9ee7cd 100644 --- a/.mock/definition/collections.yml +++ b/.mock/definition/collections.yml @@ -7,7 +7,9 @@ service: list: path: /sites/{site_id}/collections method: GET - auth: true + auth: + - OAuth2: + - cms:read docs: | List of all Collections within a Site. @@ -22,6 +24,7 @@ service: response: docs: Request was successful type: root.CollectionList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -55,9 +58,19 @@ service: create: path: /sites/{site_id}/collections method: POST - auth: true - docs: | - Create a Collection for a site. + auth: + - OAuth2: + - cms:write + docs: > + Create a Collection for a site with collection fields. + + + Each collection includes the required _name_ and _slug_ fields, which + are generated automatically. You can update the `displayName` of these + fields, but the slug for them cannot be changed. Fields slugs are + automatically converted to lowercase. Spaces in slugs are replaced with + hyphens. + Required scope | `cms:write` source: @@ -80,14 +93,19 @@ service: slug: type: optional docs: Part of a URL that identifier + fields: + type: optional> + docs: An array of custom fields to add to the collection content-type: application/json response: docs: Request was successful type: root.Collection + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError - root.NotFoundError + - root.ConflictError - root.TooManyRequestsError - root.InternalServerError examples: @@ -97,26 +115,57 @@ service: displayName: Blog Posts singularName: Blog Post slug: posts + fields: + - isRequired: true + type: PlainText + displayName: Title + helpText: The title of the blog post + - isRequired: true + type: RichText + displayName: Content + helpText: The content of the blog post + - isRequired: true + type: Reference + displayName: Author + helpText: The author of the blog post + metadata: + collectionId: 23cc2d952d4e4631ffd4345d2743db4e response: body: - id: 580e63fc8c9a982ac9b8b745 + id: 562ac0395358780a1f5e6fbd displayName: Blog Posts singularName: Blog Post - slug: post + slug: posts createdOn: '2016-10-24T19:41:48Z' lastUpdated: '2016-10-24T19:42:38Z' fields: - - id: 23cc2d952d4e4631ffd4345d2743db4e + - id: id isRequired: true isEditable: true type: PlainText - slug: name - displayName: Name - helpText: helpText + slug: title + displayName: Title + helpText: The title of the blog post + - id: id + isRequired: true + isEditable: true + type: RichText + slug: content + displayName: Content + helpText: The content of the blog post + - id: id + isRequired: true + isEditable: true + type: Reference + slug: author + displayName: Author + helpText: The author of the blog post get: path: /collections/{collection_id} method: GET - auth: true + auth: + - OAuth2: + - cms:read docs: | Get the full details of a collection from its ID. @@ -131,6 +180,7 @@ service: response: docs: Request was successful type: root.Collection + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -142,24 +192,138 @@ service: collection_id: 580e63fc8c9a982ac9b8b745 response: body: - id: 580e63fc8c9a982ac9b8b745 - displayName: Blog Posts - singularName: Blog Post - slug: post - createdOn: '2016-10-24T19:41:48Z' - lastUpdated: '2016-10-24T19:42:38Z' + id: 7f15043107e2fc95644e93807ee25dd6 + displayName: Guide Entries + singularName: Guide Entry + slug: guide-entry + createdOn: '2024-04-12T12:42:00Z' + lastUpdated: '2024-04-12T12:42:00Z' fields: - - id: 23cc2d952d4e4631ffd4345d2743db4e + - id: 5e2a1b3c4d5e6f7890a1b2c3 isRequired: true isEditable: true type: PlainText slug: name - displayName: Name + displayName: Entry Title + helpText: Name of the entry. + - id: 5e2a1b3c4d5e6f7890a1b2c4 + isRequired: true + isEditable: true + type: PlainText + slug: slug + displayName: Slug + helpText: Slug of the entry. + - id: 6f7e8d9c0b1a2e3d4c5b6a7f + isRequired: false + isEditable: true + type: PlainText + slug: summary + displayName: Summary + helpText: A short summary of the entry. + - id: 1a2b3c4d5e6f7a8b9c0d1e2f + isRequired: false + isEditable: true + type: RichText + slug: entry-html + displayName: Entry HTML + helpText: The HTML content of the entry. + - id: 7e8d9c0b1a2e3d4c5b6a7f8e + isRequired: false + isEditable: true + type: Image + slug: illustration-image + displayName: Illustration Image + helpText: An image of the entry. + - id: 2f3e4d5c6b7a8e9d0c1b2a3f + isRequired: false + isEditable: true + type: VideoLink + slug: demonstration-video + displayName: Demonstration Video + helpText: A video of the entry. + - id: 8e9d0c1b2a3f4e5d6c7b8a9e + isRequired: false + isEditable: true + type: Link + slug: more-info-link + displayName: More Info Link + helpText: A link to more information about the entry. + - id: 3f4e5d6c7b8a9e0d1c2b3a4f + isRequired: false + isEditable: true + type: Number + slug: importance-level + displayName: Importance Level + helpText: The importance level of the entry. + - id: 9e0d1c2b3a4f5e6d7c8b9a0e + isRequired: false + isEditable: true + type: Switch + slug: is-essential + displayName: Is Essential + helpText: Is this entry essential? + - id: 4f5e6d7c8b9a0e1d2c3b4a5f + isRequired: false + isEditable: true + type: Color + slug: first-mentioned + displayName: First Mentioned + helpText: Date of the first mention of the subject. + - id: 0e1d2c3b4a5f6e7d8c9b0a1e + isRequired: false + isEditable: true + type: Color + slug: towel-color + displayName: Towel Color + helpText: The color of the towel. + - id: 5f6e7d8c9b0a1e2d3c4b5a6f + isRequired: false + isEditable: true + type: Reference + slug: related-entry + displayName: Related Entry + helpText: A related entry. + - id: 1e2d3c4b5a6f7e8d9c0b1a2f + isRequired: false + isEditable: true + type: MultiReference + slug: mentioned-in-entries + displayName: Mentioned In Entries + helpText: Entries that mention this subject. + - id: 6f7e8d9c0b1a2e3d4c5b6a8f + isRequired: false + isEditable: true + type: Option + slug: item-type + displayName: Item Type + helpText: The type of item. + - id: 2e3d4c5b6a7f8e9d0c1b2a4f + isRequired: false + isEditable: true + type: File + slug: guide-file + displayName: Guide File + helpText: helpText + - id: 7f8e9d0c1b2a3f4e5d6c8b9e + isRequired: false + isEditable: true + type: Email + slug: contributor-email + displayName: Contributor Email + helpText: helpText + - id: 3a4f5e6d7c8b9a0e1d2c4b5f + isRequired: false + isEditable: true + type: Phone + slug: emergency-contact + displayName: Emergency Contact helpText: helpText delete: path: /collections/{collection_id} method: DELETE - auth: true + auth: + - OAuth2: + - cms:write docs: | Delete a collection using its ID. diff --git a/.mock/definition/collections/fields.yml b/.mock/definition/collections/fields.yml index 08dc554..8d83b9f 100644 --- a/.mock/definition/collections/fields.yml +++ b/.mock/definition/collections/fields.yml @@ -1,24 +1,3 @@ -types: - FieldCreateType: - enum: - - Color - - DateTime - - Email - - ExtFileRef - - File - - Image - - Link - - MultiImage - - Number - - Phone - - PlainText - - RichText - - Switch - - Video - docs: Choose these appropriate field type for your collection data - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml imports: root: ../__package__.yml service: @@ -28,22 +7,19 @@ service: create: path: /collections/{collection_id}/fields method: POST - auth: true + auth: + - OAuth2: + - cms:write docs: > - Create a custom field in a collection. + Create a custom field in a collection. - Slugs must be all lowercase letters without spaces. + Field validation is currently not available through the API. - If you pass a string with uppercase letters and/or spaces to the "Slug" - property, Webflow will - convert the slug to lowercase and replace spaces with "-." - - - Only some field types can be created through the API. - - This endpoint does not currently support bulk creation. + Bulk creation of fields is not supported with this endpoint. To add + multiple fields at once, include them when you [create the + collection.](/data/v2.0.0/reference/cms/collections/create) Required scope | `cms:write` @@ -55,52 +31,94 @@ service: docs: Unique identifier for a Collection display-name: Create Collection Field request: - name: FieldCreate - body: - properties: - isRequired: - type: optional - docs: define whether a field is required in a collection - type: - type: FieldCreateType - docs: Choose these appropriate field type for your collection data - displayName: - type: string - docs: The name of a field - helpText: - type: optional - docs: Additional text to help anyone filling out this field + body: root.FieldCreate content-type: application/json response: docs: Request was successful - type: root.Field + type: root.FieldCreate + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError - root.NotFoundError + - root.ConflictError - root.TooManyRequestsError - root.InternalServerError examples: - - path-parameters: + - name: StaticField + path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 request: + id: 562ac0395358780a1f5e6fbc + isEditable: true isRequired: false type: RichText displayName: Post Body helpText: Add the body of your post here response: body: - id: 75821f618da60c18383330bcc0ca488b - isRequired: false + id: 562ac0395358780a1f5e6fbc isEditable: true + isRequired: false type: RichText - slug: post-body displayName: Post Body helpText: Add the body of your post here + - name: OptionField + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + id: 562ac0395358780a1f5e6fbc + isEditable: true + isRequired: false + type: Option + displayName: Post Type + helpText: Add the body of your post here + metadata: + options: + - name: Feature + - name: News + - name: Product Highlight + response: + body: + id: 562ac0395358780a1f5e6fbc + isEditable: true + isRequired: false + type: Option + displayName: Post Type + helpText: Add the body of your post here + metadata: + options: + - name: Feature + - name: News + - name: Product Highlight + - name: ReferenceField + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + id: 562ac0395358780a1f5e6fbd + isEditable: true + isRequired: false + type: Reference + displayName: Author + helpText: Add the post author here + metadata: + collectionId: 63692ab61fb2852f582ba8f5 + response: + body: + id: 562ac0395358780a1f5e6fbd + isEditable: true + isRequired: false + type: Reference + displayName: Author + helpText: Add the post author here + metadata: + collectionId: 63692ab61fb2852f582ba8f5 delete: path: /collections/{collection_id}/fields/{field_id} method: DELETE - auth: true + auth: + - OAuth2: + - cms:write docs: > Delete a custom field in a collection. This endpoint does not currently support bulk deletion. @@ -130,7 +148,9 @@ service: update: path: /collections/{collection_id}/fields/{field_id} method: PATCH - auth: true + auth: + - OAuth2: + - cms:write docs: | Update a custom field in a collection. @@ -162,6 +182,7 @@ service: response: docs: Request was successful type: root.Field + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -185,5 +206,7 @@ service: slug: post-body displayName: Post Body helpText: Add the body of your post here + validations: + additionalProperties: additionalProperties source: openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/collections/items.yml b/.mock/definition/collections/items.yml index f765817..57e6402 100644 --- a/.mock/definition/collections/items.yml +++ b/.mock/definition/collections/items.yml @@ -1,3 +1,5 @@ +imports: + root: ../__package__.yml types: ItemsListItemsRequestSortBy: enum: @@ -20,11 +22,11 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true - ItemsCreateItemRequest: + ItemsCreateItemRequestBody: discriminated: false union: - root.CollectionItemPostSingle - - Multiple Items + - type: Multiple Items source: openapi: ../../../openapi/referenced-specs/v2.yml ItemsDeleteItemsRequestItemsItem: @@ -38,6 +40,13 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true + ItemsUpdateItemsResponse: + discriminated: false + union: + - type: root.CollectionItem + - type: root.CollectionItemList + source: + openapi: ../../../openapi/referenced-specs/v2.yml ItemsListItemsLiveRequestSortBy: enum: - lastPublished @@ -59,16 +68,16 @@ types: source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true - ItemsCreateItemLiveRequest: + ItemsCreateItemLiveRequestBody: discriminated: false union: - - root.CollectionItem - - Multiple Live Items + - type: root.CollectionItem + - type: Multiple Live Items source: openapi: ../../../openapi/referenced-specs/v2.yml ItemsDeleteItemsLiveRequestItemsItem: properties: - itemId: + id: type: string docs: Unique identifier for the Item cmsLocaleIds: @@ -113,20 +122,52 @@ types: CreateBulkCollectionItemRequestBodyFieldData: discriminated: false union: - - Single CMS Item + - type: Single CMS Item - docs: A list of CMS items to create type: list source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true + Item IDs: + docs: An array of Item IDs in a single locale + properties: + itemIds: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ItemsPublishItemRequestItemsItemsItem: + properties: + id: + type: string + docs: The ID of the CMS item + cmsLocaleIds: + type: optional> + docs: Array of identifiers for the locales where the item will be published + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + Item IDs with Locales: + docs: An array of Item IDs with included `cmsLocaleIds` + properties: + items: optional> + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ItemsPublishItemRequest: + discriminated: false + union: + - type: Item IDs + docs: An array of Item IDs in a single locale + - type: Item IDs with Locales + docs: An array of Item IDs with included `cmsLocaleIds` + source: + openapi: ../../../openapi/referenced-specs/v2.yml ItemsPublishItemResponse: properties: publishedItemIds: optional> errors: optional> source: openapi: ../../../openapi/referenced-specs/v2.yml -imports: - root: ../__package__.yml service: auth: false base-path: '' @@ -134,7 +175,9 @@ service: list-items: path: /collections/{collection_id}/items method: GET - auth: true + auth: + - OAuth2: + - cms:read docs: | List of all Items within a Collection. @@ -157,19 +200,22 @@ service: response. To query multiple locales, input a comma separated string. offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' name: type: optional - docs: The name of the item(s) + docs: Filter by the exact name of the item(s) slug: type: optional - docs: The slug of the item + docs: Filter by the exact slug of the item + lastPublished: + type: optional + docs: Filter by the last published date of the item(s) sortBy: type: optional docs: Sort results by the provided value @@ -179,6 +225,7 @@ service: response: docs: Request was successful type: root.CollectionItemList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -188,6 +235,14 @@ service: examples: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + cmsLocaleId: cmsLocaleId + offset: 1 + limit: 1 + name: name + slug: slug + sortBy: lastPublished + sortOrder: asc response: body: items: @@ -222,14 +277,16 @@ service: create-item: path: /collections/{collection_id}/items method: POST - auth: true + auth: + - OAuth2: + - cms:write docs: > Create Item(s) in a Collection. To create items across multiple locales, please use [this - endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write` @@ -241,11 +298,20 @@ service: docs: Unique identifier for a Collection display-name: Create Collection Item(s) request: - body: ItemsCreateItemRequest + body: ItemsCreateItemRequestBody + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. + name: ItemsCreateItemRequest content-type: application/json response: docs: Request was successful type: root.CollectionItem + status-code: 202 errors: - root.BadRequestError - root.UnauthorizedError @@ -256,15 +322,44 @@ service: - name: SingleItem path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: isArchived: false isDraft: false fieldData: - name: Pan Galactic Gargle Blaster Recipe - slug: pan-galactic-gargle-blaster - date: '2022-11-18T00:00:00.000Z' - featured: true - color: '#db4b68' + name: The Hitchhiker's Guide to the Galaxy + slug: hitchhikers-guide-to-the-galaxy + plain-text: Don't Panic. + rich-text: >- +

A Guide to Interstellar Travel

A towel is about the + most massively useful thing an interstellar hitchhiker can have. + Don't forget yours!

+ main-image: + fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + image-gallery: + - fileId: 62b720ef280c7a7a3be8cabd + url: /files/62b720ef280c7a7a3be8cabd_image.png + - fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 + official-site: >- + https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy + contact-email: zaphod.beeblebrox@heartofgold.gov + support-phone: 424-242-4242 + answer-to-everything: 42 + release-date: '1979-10-12T00:00:00.000Z' + is-featured: true + brand-color: '#000000' + category: 62b720ef280c7a7a3be8cabf + author: 62b720ef280c7a7a3be8cab0 + tags: + - 62b720ef280c7a7a3be8cab1 + - 62b720ef280c7a7a3be8cab2 + downloadable-asset: + fileId: 62b720ef280c7a7a3be8cab3 + url: /files/62b720ef280c7a7a3be8cab3_document.pdf response: body: id: 42b720ef280c7a7a3be8cabe @@ -275,14 +370,43 @@ service: isArchived: false isDraft: false fieldData: - name: Pan Galactic Gargle Blaster Recipe - slug: pan-galactic-gargle-blaster - color: '#db4b68' - date: '2022-11-18T00:00:00.000Z' - featured: true + name: The Hitchhiker's Guide to the Galaxy + slug: hitchhikers-guide-to-the-galaxy + plain-text: Don't Panic. + rich-text: >- +

A Guide to Interstellar Travel

A towel is about the + most massively useful thing an interstellar hitchhiker can + have. Don't forget yours!

+ main-image: + fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + image-gallery: + - fileId: 62b720ef280c7a7a3be8cabd + url: /files/62b720ef280c7a7a3be8cabd_image.png + - fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 + official-site: >- + https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy + contact-email: zaphod.beeblebrox@heartofgold.gov + support-phone: 424-242-4242 + answer-to-everything: 42 + release-date: '1979-10-12T00:00:00.000Z' + is-featured: true + brand-color: '#000000' + category: 62b720ef280c7a7a3be8cabf + author: 62b720ef280c7a7a3be8cab0 + tags: + - 62b720ef280c7a7a3be8cab1 + - 62b720ef280c7a7a3be8cab2 + downloadable-asset: + fileId: 62b720ef280c7a7a3be8cab3 + url: /files/62b720ef280c7a7a3be8cab3_document.pdf - name: MultipleItems path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: items: - isArchived: false @@ -317,13 +441,15 @@ service: delete-items: path: /collections/{collection_id}/items method: DELETE - auth: true + auth: + - OAuth2: + - cms:write docs: > Delete Items from a Collection. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the - items are localized, items will be deleted only in the primary locale. + Items will only be deleted in the primary + locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -338,7 +464,7 @@ service: name: ItemsDeleteItemsRequest body: properties: - items: optional> + items: list content-type: application/json errors: - root.BadRequestError @@ -350,17 +476,24 @@ service: examples: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 - request: {} + request: + items: + - id: 580e64008c9a982ac9b8b754 update-items: path: /collections/{collection_id}/items method: PATCH - auth: true + auth: + - OAuth2: + - cms:write docs: > - Update a single item or multiple items (up to 100) in a Collection. + Update a single item or multiple items in a Collection. + + The limit for this endpoint is 100 items. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the - items are localized, items will be updated only in the primary locale. + + Items will only be updated in the primary + locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -373,13 +506,21 @@ service: display-name: Update Collection Items request: name: ItemsUpdateItemsRequest + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. body: properties: items: optional> content-type: application/json response: docs: Request was successful - type: root.CollectionItem + type: ItemsUpdateItemsResponse + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -390,6 +531,8 @@ service: - name: LocalizedItems path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: items: - id: 66f6ed9576ddacf3149d5ea6 @@ -418,22 +561,60 @@ service: featured: false response: body: - id: id - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' + items: + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + lastPublished: '2024-09-27T17:38:29.066Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: false + isDraft: false + fieldData: + name: Ne Paniquez Pas + slug: ne-paniquez-pas + featured: false + - id: 66f6ed9576ddacf3149d5ea6 + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + lastPublished: '2024-09-27T17:38:29.066Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: false + isDraft: false + fieldData: + name: No Entrar en Pánico + slug: no-entrar-en-panico + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca5 + lastPublished: '2024-09-27T17:38:29.066Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: false + isDraft: false + fieldData: + name: Au Revoir et Merci pour Tous les Poissons + slug: au-revoir-et-merci + featured: false + - id: 66f6ed9576ddacf3149d5eaa + cmsLocaleId: 66f6e966c9e1dc700a857ca4 + lastPublished: '2024-09-27T17:38:29.066Z' + lastUpdated: '2024-09-27T17:38:29.066Z' + createdOn: '2024-09-27T17:38:29.066Z' + isArchived: false + isDraft: false + fieldData: + name: Hasta Luego y Gracias por Todo el Pescado + slug: hasta-luego-y-gracias + featured: false + pagination: + limit: 25 + offset: 0 + total: 4 - name: MultipleItems path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: items: - id: 580e64008c9a982ac9b8b754 @@ -454,113 +635,47 @@ service: department: Product response: body: - id: id - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' - - name: Multiple items updated across multiple locales - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - response: - body: - id: id - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' - - name: Mulitple items updated in a single locale - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - response: - body: - id: id - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' + items: + - id: 62b720ef280c7a7a3be8cabe + cmsLocaleId: 66f6e966c9e1dc700a857ca3 + lastPublished: '2022-06-30T13:35:20.878Z' + lastUpdated: '2022-06-25T14:51:27.809Z' + createdOn: '2022-06-25T14:51:27.809Z' + isArchived: false + isDraft: false + fieldData: + name: Senior Data Analyst + slug: senior-data-analyst + url: https://boards.greenhouse.io/webflow/jobs/26567701 + department: Data + - id: 62c880ef281c7b7b4cf9dabc + cmsLocaleId: 66f6e966c9e1dc700a857ca3 + lastPublished: '2023-04-15T10:25:18.123Z' + lastUpdated: '2023-04-10T11:45:30.567Z' + createdOn: '2023-04-10T11:45:30.567Z' + isArchived: false + isDraft: false + fieldData: + name: Product Manager + slug: product-manager + url: https://boards.greenhouse.io/webflow/jobs/31234567 + department: Product + pagination: + limit: 25 + offset: 0 + total: 2 list-items-live: path: /collections/{collection_id}/items/live method: GET - auth: true + auth: + - OAuth2: + - cms:read docs: | - List of all live Items within a Collection. + List all published items in a collection. + + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + Required scope | `CMS:read` source: @@ -581,19 +696,22 @@ service: response. To query multiple locales, input a comma separated string. offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' name: type: optional - docs: The name of the item(s) + docs: Filter by the exact name of the item(s) slug: type: optional - docs: The slug of the item + docs: Filter by the exact slug of the item + lastPublished: + type: optional + docs: Filter by the last published date of the item(s) sortBy: type: optional docs: Sort results by the provided value @@ -603,6 +721,8 @@ service: response: docs: Request was successful type: root.CollectionItemList + status-code: 200 + url: Data API errors: - root.BadRequestError - root.UnauthorizedError @@ -612,6 +732,14 @@ service: examples: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + cmsLocaleId: cmsLocaleId + offset: 1 + limit: 1 + name: name + slug: slug + sortBy: lastPublished + sortOrder: asc response: body: items: @@ -646,15 +774,17 @@ service: create-item-live: path: /collections/{collection_id}/items/live method: POST - auth: true + auth: + - OAuth2: + - cms:write docs: > - Create live Item(s) in a Collection. The Item(s) will be published to - the live site. + Create item(s) in a collection that will be immediately published to the + live site. To create items across multiple locales, [please use this - endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + endpoint.](/data/reference/cms/collection-items/staged-items/create-items) @@ -667,11 +797,20 @@ service: docs: Unique identifier for a Collection display-name: Create Live Collection Item(s) request: - body: ItemsCreateItemLiveRequest + body: ItemsCreateItemLiveRequestBody + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. + name: ItemsCreateItemLiveRequest content-type: application/json response: docs: Request was successful type: root.CollectionItem + status-code: 202 errors: - root.BadRequestError - root.UnauthorizedError @@ -682,15 +821,44 @@ service: - name: SingleItem path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: isArchived: false isDraft: false fieldData: - name: Pan Galactic Gargle Blaster Recipe - slug: pan-galactic-gargle-blaster - date: '2022-11-18T00:00:00.000Z' - featured: true - color: '#db4b68' + name: The Hitchhiker's Guide to the Galaxy + slug: hitchhikers-guide-to-the-galaxy + plain-text: Don't Panic. + rich-text: >- +

A Guide to Interstellar Travel

A towel is about the + most massively useful thing an interstellar hitchhiker can have. + Don't forget yours!

+ main-image: + fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + image-gallery: + - fileId: 62b720ef280c7a7a3be8cabd + url: /files/62b720ef280c7a7a3be8cabd_image.png + - fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 + official-site: >- + https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy + contact-email: zaphod.beeblebrox@heartofgold.gov + support-phone: 424-242-4242 + answer-to-everything: 42 + release-date: '1979-10-12T00:00:00.000Z' + is-featured: true + brand-color: '#000000' + category: 62b720ef280c7a7a3be8cabf + author: 62b720ef280c7a7a3be8cab0 + tags: + - 62b720ef280c7a7a3be8cab1 + - 62b720ef280c7a7a3be8cab2 + downloadable-asset: + fileId: 62b720ef280c7a7a3be8cab3 + url: /files/62b720ef280c7a7a3be8cab3_document.pdf response: body: id: 42b720ef280c7a7a3be8cabe @@ -701,14 +869,43 @@ service: isArchived: false isDraft: false fieldData: - name: Pan Galactic Gargle Blaster Recipe - slug: pan-galactic-gargle-blaster - color: '#db4b68' - date: '2022-11-18T00:00:00.000Z' - featured: true + name: The Hitchhiker's Guide to the Galaxy + slug: hitchhikers-guide-to-the-galaxy + plain-text: Don't Panic. + rich-text: >- +

A Guide to Interstellar Travel

A towel is about the + most massively useful thing an interstellar hitchhiker can + have. Don't forget yours!

+ main-image: + fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + image-gallery: + - fileId: 62b720ef280c7a7a3be8cabd + url: /files/62b720ef280c7a7a3be8cabd_image.png + - fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 + official-site: >- + https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy + contact-email: zaphod.beeblebrox@heartofgold.gov + support-phone: 424-242-4242 + answer-to-everything: 42 + release-date: '1979-10-12T00:00:00.000Z' + is-featured: true + brand-color: '#000000' + category: 62b720ef280c7a7a3be8cabf + author: 62b720ef280c7a7a3be8cab0 + tags: + - 62b720ef280c7a7a3be8cab1 + - 62b720ef280c7a7a3be8cab2 + downloadable-asset: + fileId: 62b720ef280c7a7a3be8cab3 + url: /files/62b720ef280c7a7a3be8cab3_document.pdf - name: MultipleItems path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: items: - isArchived: false @@ -735,24 +932,51 @@ service: isArchived: false isDraft: false fieldData: - name: Pan Galactic Gargle Blaster Recipe - slug: pan-galactic-gargle-blaster - color: '#db4b68' - date: '2022-11-18T00:00:00.000Z' - featured: true + name: The Hitchhiker's Guide to the Galaxy + slug: hitchhikers-guide-to-the-galaxy + plain-text: Don't Panic. + rich-text: >- +

A Guide to Interstellar Travel

A towel is about the + most massively useful thing an interstellar hitchhiker can + have. Don't forget yours!

+ main-image: + fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + image-gallery: + - fileId: 62b720ef280c7a7a3be8cabd + url: /files/62b720ef280c7a7a3be8cabd_image.png + - fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 + official-site: >- + https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy + contact-email: zaphod.beeblebrox@heartofgold.gov + support-phone: 424-242-4242 + answer-to-everything: 42 + release-date: '1979-10-12T00:00:00.000Z' + is-featured: true + brand-color: '#000000' + category: 62b720ef280c7a7a3be8cabf + author: 62b720ef280c7a7a3be8cab0 + tags: + - 62b720ef280c7a7a3be8cab1 + - 62b720ef280c7a7a3be8cab2 + downloadable-asset: + fileId: 62b720ef280c7a7a3be8cab3 + url: /files/62b720ef280c7a7a3be8cab3_document.pdf delete-items-live: path: /collections/{collection_id}/items/live method: DELETE - auth: true + auth: + - OAuth2: + - cms:write docs: > - Remove an item or multiple items (up to 100 items) from the live site. - Deleting published items will unpublish the items from the live site and - set them to draft. + Unpublish up to 100 items from the live site and set the `isDraft` + property to `true`. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the - items are localized, items will be unpublished only in the primary - locale. + Items will only be unpublished in the + primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -762,12 +986,12 @@ service: collection_id: type: string docs: Unique identifier for a Collection - display-name: Delete Live Collection Items + display-name: Unpublish Live Collection Items request: name: ItemsDeleteItemsLiveRequest body: properties: - items: optional> + items: list content-type: application/json errors: - root.BadRequestError @@ -778,18 +1002,22 @@ service: examples: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 - request: {} + request: + items: + - id: 580e64008c9a982ac9b8b754 update-items-live: path: /collections/{collection_id}/items/live method: PATCH - auth: true + auth: + - OAuth2: + - cms:write docs: > - Update a single live item or multiple live items (up to 100) in a - Collection + Update a single published item or multiple published items (up to 100) + in a Collection - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the - items are localized, items will be updated only in the primary locale. + Items will only be updated in the primary + locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -802,6 +1030,13 @@ service: display-name: Update Live Collection Items request: name: ItemsUpdateItemsLiveRequest + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. body: properties: items: optional> @@ -809,16 +1044,20 @@ service: response: docs: Request was successful type: root.CollectionItemListNoPagination + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError - root.NotFoundError + - root.ConflictError - root.TooManyRequestsError - root.InternalServerError examples: - name: LocalizedItems path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: items: - id: 66f6ed9576ddacf3149d5ea6 @@ -850,44 +1089,44 @@ service: items: - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Ne Paniquez Pas slug: ne-paniquez-pas featured: false - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: No Entrar en Pánico slug: no-entrar-en-panico featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Au Revoir et Merci pour Tous les Poissons slug: au-revoir-et-merci featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Hasta Luego y Gracias por Todo el Pescado slug: hasta-luego-y-gracias @@ -895,6 +1134,8 @@ service: - name: MultipleItems path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: items: - id: 580e64008c9a982ac9b8b754 @@ -918,44 +1159,44 @@ service: items: - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Ne Paniquez Pas slug: ne-paniquez-pas featured: false - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: No Entrar en Pánico slug: no-entrar-en-panico featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Au Revoir et Merci pour Tous les Poissons slug: au-revoir-et-merci featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Hasta Luego y Gracias por Todo el Pescado slug: hasta-luego-y-gracias @@ -963,6 +1204,8 @@ service: - name: Multiple items updated across multiple locales path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: items: - id: 66f6ed9576ddacf3149d5ea6 @@ -994,51 +1237,53 @@ service: items: - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Ne Paniquez Pas slug: ne-paniquez-pas featured: false - id: 66f6ed9576ddacf3149d5ea6 cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: No Entrar en Pánico slug: no-entrar-en-panico featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Au Revoir et Merci pour Tous les Poissons slug: au-revoir-et-merci featured: false - id: 66f6ed9576ddacf3149d5eaa cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2023-03-17T18:47:35.560Z' + lastPublished: '2024-09-27T17:38:29.066Z' lastUpdated: '2024-09-27T17:38:29.066Z' createdOn: '2024-09-27T17:38:29.066Z' - isArchived: true - isDraft: true + isArchived: false + isDraft: false fieldData: name: Hasta Luego y Gracias por Todo el Pescado slug: hasta-luego-y-gracias featured: false - - name: Mulitple items updated in a single locale + - name: Multiple items updated in a single locale path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: items: - id: 66f6ed9576ddacf3149d5ea6 @@ -1095,15 +1340,19 @@ service: create-items: path: /collections/{collection_id}/items/bulk method: POST - auth: true + auth: + - OAuth2: + - cms:write docs: > Create an item or multiple items in a CMS Collection across multiple corresponding locales. - **Notes:** + - This endpoint can create up to 100 items in a request. - - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. + - If the `cmsLocaleIds` parameter is not included in the request, an item will only be created in the primary locale. + + Required scope | `CMS:write` source: @@ -1115,6 +1364,13 @@ service: display-name: Create Collection Items request: name: CreateBulkCollectionItemRequestBody + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. body: properties: cmsLocaleIds: @@ -1129,12 +1385,13 @@ service: isDraft: type: optional docs: Indicates whether the item is in draft state. - default: false + default: true fieldData: CreateBulkCollectionItemRequestBodyFieldData content-type: application/json response: docs: Request was successful type: root.BulkCollectionItem + status-code: 202 errors: - root.BadRequestError - root.UnauthorizedError @@ -1145,6 +1402,8 @@ service: - name: Create a single item across multiple locales path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: cmsLocaleIds: - 66f6e966c9e1dc700a857ca3 @@ -1173,9 +1432,11 @@ service: date: '2022-11-18T00:00:00.000Z' featured: false color: '#db4b68' - - name: Create multiple items across multipel locales + - name: Create multiple items across multiple locales path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: cmsLocaleIds: - 66f6e966c9e1dc700a857ca3 @@ -1208,6 +1469,8 @@ service: - name: Single item created across multiple locales path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: cmsLocaleIds: - 66f6e966c9e1dc700a857ca3 @@ -1239,6 +1502,8 @@ service: - name: Multiple items created across multiple locales path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 + query-parameters: + skipInvalidFiles: true request: cmsLocaleIds: - 66f6e966c9e1dc700a857ca3 @@ -1270,7 +1535,9 @@ service: get-item: path: /collections/{collection_id}/items/{item_id} method: GET - auth: true + auth: + - OAuth2: + - cms:read docs: | Get details of a selected Collection Item. @@ -1298,6 +1565,7 @@ service: response: docs: Request was successful type: root.CollectionItem + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -1308,6 +1576,8 @@ service: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 item_id: 580e64008c9a982ac9b8b754 + query-parameters: + cmsLocaleId: cmsLocaleId response: body: id: 42b720ef280c7a7a3be8cabe @@ -1318,19 +1588,46 @@ service: isArchived: false isDraft: false fieldData: - name: Pan Galactic Gargle Blaster Recipe - slug: pan-galactic-gargle-blaster - color: '#db4b68' - date: '2022-11-18T00:00:00.000Z' - featured: true + name: The Hitchhiker's Guide to the Galaxy + slug: hitchhikers-guide-to-the-galaxy + plain-text: Don't Panic. + rich-text: >- +

A Guide to Interstellar Travel

A towel is about the + most massively useful thing an interstellar hitchhiker can + have. Don't forget yours!

+ main-image: + fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + image-gallery: + - fileId: 62b720ef280c7a7a3be8cabd + url: /files/62b720ef280c7a7a3be8cabd_image.png + - fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 + official-site: >- + https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy + contact-email: zaphod.beeblebrox@heartofgold.gov + support-phone: 424-242-4242 + answer-to-everything: 42 + release-date: '1979-10-12T00:00:00.000Z' + is-featured: true + brand-color: '#000000' + category: 62b720ef280c7a7a3be8cabf + author: 62b720ef280c7a7a3be8cab0 + tags: + - 62b720ef280c7a7a3be8cab1 + - 62b720ef280c7a7a3be8cab2 + downloadable-asset: + fileId: 62b720ef280c7a7a3be8cab3 + url: /files/62b720ef280c7a7a3be8cab3_document.pdf delete-item: path: /collections/{collection_id}/items/{item_id} method: DELETE - auth: true - docs: > - Delete an Item from a Collection. This endpoint does not currently - support bulk deletion. - + auth: + - OAuth2: + - cms:write + docs: | + Delete an item from a collection. Required scope | `CMS:write` source: @@ -1363,10 +1660,14 @@ service: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 item_id: 580e64008c9a982ac9b8b754 + query-parameters: + cmsLocaleId: cmsLocaleId update-item: path: /collections/{collection_id}/items/{item_id} method: PATCH - auth: true + auth: + - OAuth2: + - cms:write docs: | Update a selected Item in a Collection. @@ -1383,10 +1684,19 @@ service: display-name: Update Collection Item request: body: root.CollectionItemPatchSingle + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. + name: ItemsUpdateItemRequest content-type: application/json response: docs: Request was successful type: root.CollectionItem + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -1397,15 +1707,44 @@ service: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 item_id: 580e64008c9a982ac9b8b754 + query-parameters: + skipInvalidFiles: true request: isArchived: false isDraft: false fieldData: - name: Pan Galactic Gargle Blaster Recipe - slug: pan-galactic-gargle-blaster - date: '2022-11-18T00:00:00.000Z' - featured: true - color: '#db4b68' + name: The Hitchhiker's Guide to the Galaxy + slug: hitchhikers-guide-to-the-galaxy + plain-text: Don't Panic. + rich-text: >- +

A Guide to Interstellar Travel

A towel is about the + most massively useful thing an interstellar hitchhiker can have. + Don't forget yours!

+ main-image: + fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + image-gallery: + - fileId: 62b720ef280c7a7a3be8cabd + url: /files/62b720ef280c7a7a3be8cabd_image.png + - fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 + official-site: >- + https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy + contact-email: zaphod.beeblebrox@heartofgold.gov + support-phone: 424-242-4242 + answer-to-everything: 42 + release-date: '1979-10-12T00:00:00.000Z' + is-featured: true + brand-color: '#000000' + category: 62b720ef280c7a7a3be8cabf + author: 62b720ef280c7a7a3be8cab0 + tags: + - 62b720ef280c7a7a3be8cab1 + - 62b720ef280c7a7a3be8cab2 + downloadable-asset: + fileId: 62b720ef280c7a7a3be8cab3 + url: /files/62b720ef280c7a7a3be8cab3_document.pdf response: body: id: 42b720ef280c7a7a3be8cabe @@ -1416,18 +1755,51 @@ service: isArchived: false isDraft: false fieldData: - name: Pan Galactic Gargle Blaster Recipe - slug: pan-galactic-gargle-blaster - color: '#db4b68' - date: '2022-11-18T00:00:00.000Z' - featured: true + name: The Hitchhiker's Guide to the Galaxy + slug: hitchhikers-guide-to-the-galaxy + plain-text: Don't Panic. + rich-text: >- +

A Guide to Interstellar Travel

A towel is about the + most massively useful thing an interstellar hitchhiker can + have. Don't forget yours!

+ main-image: + fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + image-gallery: + - fileId: 62b720ef280c7a7a3be8cabd + url: /files/62b720ef280c7a7a3be8cabd_image.png + - fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 + official-site: >- + https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy + contact-email: zaphod.beeblebrox@heartofgold.gov + support-phone: 424-242-4242 + answer-to-everything: 42 + release-date: '1979-10-12T00:00:00.000Z' + is-featured: true + brand-color: '#000000' + category: 62b720ef280c7a7a3be8cabf + author: 62b720ef280c7a7a3be8cab0 + tags: + - 62b720ef280c7a7a3be8cab1 + - 62b720ef280c7a7a3be8cab2 + downloadable-asset: + fileId: 62b720ef280c7a7a3be8cab3 + url: /files/62b720ef280c7a7a3be8cab3_document.pdf get-item-live: path: /collections/{collection_id}/items/{item_id}/live method: GET - auth: true + auth: + - OAuth2: + - cms:read docs: | Get details of a selected Collection live Item. + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + + Required scope | `CMS:read` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -1452,6 +1824,8 @@ service: response: docs: Request was successful type: root.CollectionItem + status-code: 200 + url: Data API errors: - root.BadRequestError - root.UnauthorizedError @@ -1462,6 +1836,8 @@ service: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 item_id: 580e64008c9a982ac9b8b754 + query-parameters: + cmsLocaleId: cmsLocaleId response: body: id: 42b720ef280c7a7a3be8cabe @@ -1472,21 +1848,51 @@ service: isArchived: false isDraft: false fieldData: - name: Pan Galactic Gargle Blaster Recipe - slug: pan-galactic-gargle-blaster - color: '#db4b68' - date: '2022-11-18T00:00:00.000Z' - featured: true + name: The Hitchhiker's Guide to the Galaxy + slug: hitchhikers-guide-to-the-galaxy + plain-text: Don't Panic. + rich-text: >- +

A Guide to Interstellar Travel

A towel is about the + most massively useful thing an interstellar hitchhiker can + have. Don't forget yours!

+ main-image: + fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + image-gallery: + - fileId: 62b720ef280c7a7a3be8cabd + url: /files/62b720ef280c7a7a3be8cabd_image.png + - fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 + official-site: >- + https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy + contact-email: zaphod.beeblebrox@heartofgold.gov + support-phone: 424-242-4242 + answer-to-everything: 42 + release-date: '1979-10-12T00:00:00.000Z' + is-featured: true + brand-color: '#000000' + category: 62b720ef280c7a7a3be8cabf + author: 62b720ef280c7a7a3be8cab0 + tags: + - 62b720ef280c7a7a3be8cab1 + - 62b720ef280c7a7a3be8cab2 + downloadable-asset: + fileId: 62b720ef280c7a7a3be8cab3 + url: /files/62b720ef280c7a7a3be8cab3_document.pdf delete-item-live: path: /collections/{collection_id}/items/{item_id}/live method: DELETE - auth: true + auth: + - OAuth2: + - cms:write docs: > - Remove a live item from the site. Removing a published item will - unpublish the item from the live site and set it to draft. + Unpublish a live item from the site and set the `isDraft` property to + `true`. - This endpoint does not currently support bulk deletion. + For bulk unpublishing, please use [this + endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) Required scope | `CMS:write` @@ -1499,7 +1905,7 @@ service: item_id: type: string docs: Unique identifier for an Item - display-name: Delete Live Collection Item + display-name: Unpublish Live Collection Item request: name: ItemsDeleteItemLiveRequest query-parameters: @@ -1520,10 +1926,14 @@ service: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 item_id: 580e64008c9a982ac9b8b754 + query-parameters: + cmsLocaleId: cmsLocaleId update-item-live: path: /collections/{collection_id}/items/{item_id}/live method: PATCH - auth: true + auth: + - OAuth2: + - cms:write docs: > Update a selected live Item in a Collection. The updates for this Item will be published to the live site. @@ -1542,29 +1952,68 @@ service: display-name: Update Live Collection Item request: body: root.CollectionItemPatchSingle + query-parameters: + skipInvalidFiles: + type: optional + default: true + docs: >- + When true, invalid files are skipped and processing continues. + When false, the entire request fails if any file is invalid. + name: ItemsUpdateItemLiveRequest content-type: application/json response: docs: Request was successful type: root.CollectionItem + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError - root.NotFoundError + - root.ConflictError - root.TooManyRequestsError - root.InternalServerError examples: - path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 item_id: 580e64008c9a982ac9b8b754 + query-parameters: + skipInvalidFiles: true request: isArchived: false isDraft: false fieldData: - name: Pan Galactic Gargle Blaster Recipe - slug: pan-galactic-gargle-blaster - date: '2022-11-18T00:00:00.000Z' - featured: true - color: '#db4b68' + name: The Hitchhiker's Guide to the Galaxy + slug: hitchhikers-guide-to-the-galaxy + plain-text: Don't Panic. + rich-text: >- +

A Guide to Interstellar Travel

A towel is about the + most massively useful thing an interstellar hitchhiker can have. + Don't forget yours!

+ main-image: + fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + image-gallery: + - fileId: 62b720ef280c7a7a3be8cabd + url: /files/62b720ef280c7a7a3be8cabd_image.png + - fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 + official-site: >- + https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy + contact-email: zaphod.beeblebrox@heartofgold.gov + support-phone: 424-242-4242 + answer-to-everything: 42 + release-date: '1979-10-12T00:00:00.000Z' + is-featured: true + brand-color: '#000000' + category: 62b720ef280c7a7a3be8cabf + author: 62b720ef280c7a7a3be8cab0 + tags: + - 62b720ef280c7a7a3be8cab1 + - 62b720ef280c7a7a3be8cab2 + downloadable-asset: + fileId: 62b720ef280c7a7a3be8cab3 + url: /files/62b720ef280c7a7a3be8cab3_document.pdf response: body: id: 42b720ef280c7a7a3be8cabe @@ -1575,15 +2024,44 @@ service: isArchived: false isDraft: false fieldData: - name: Pan Galactic Gargle Blaster Recipe - slug: pan-galactic-gargle-blaster - color: '#db4b68' - date: '2022-11-18T00:00:00.000Z' - featured: true + name: The Hitchhiker's Guide to the Galaxy + slug: hitchhikers-guide-to-the-galaxy + plain-text: Don't Panic. + rich-text: >- +

A Guide to Interstellar Travel

A towel is about the + most massively useful thing an interstellar hitchhiker can + have. Don't forget yours!

+ main-image: + fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + image-gallery: + - fileId: 62b720ef280c7a7a3be8cabd + url: /files/62b720ef280c7a7a3be8cabd_image.png + - fileId: 62b720ef280c7a7a3be8cabe + url: /files/62b720ef280c7a7a3be8cabe_image.png + intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 + official-site: >- + https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy + contact-email: zaphod.beeblebrox@heartofgold.gov + support-phone: 424-242-4242 + answer-to-everything: 42 + release-date: '1979-10-12T00:00:00.000Z' + is-featured: true + brand-color: '#000000' + category: 62b720ef280c7a7a3be8cabf + author: 62b720ef280c7a7a3be8cab0 + tags: + - 62b720ef280c7a7a3be8cab1 + - 62b720ef280c7a7a3be8cab2 + downloadable-asset: + fileId: 62b720ef280c7a7a3be8cab3 + url: /files/62b720ef280c7a7a3be8cab3_document.pdf publish-item: path: /collections/{collection_id}/items/publish method: POST - auth: true + auth: + - OAuth2: + - cms:write docs: | Publish an item or multiple items. @@ -1596,14 +2074,12 @@ service: docs: Unique identifier for a Collection display-name: Publish Collection Item request: - name: ItemsPublishItemRequest - body: - properties: - itemIds: list + body: ItemsPublishItemRequest content-type: application/json response: docs: Request was successful type: ItemsPublishItemResponse + status-code: 202 errors: - root.BadRequestError - root.UnauthorizedError @@ -1612,11 +2088,52 @@ service: - root.TooManyRequestsError - root.InternalServerError examples: - - path-parameters: + - name: PrimaryLocale + path-parameters: collection_id: 580e63fc8c9a982ac9b8b745 request: itemIds: - - itemIds + - 643fd856d66b6528195ee2ca + - 643fd856d66b6528195ee2cb + - 643fd856d66b6528195ee2cc + response: + body: + publishedItemIds: + - 643fd856d66b6528195ee2ca + - 643fd856d66b6528195ee2cb + errors: + - Staging item ID 643fd856d66b6528195ee2cf not found. + - name: SecondaryLocale + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 643fd856d66b6528195ee2ca + cmsLocaleIds: + - 653ad57de882f528b32e810e + - id: 643fd856d66b6528195ee2cb + cmsLocaleIds: + - 653ad57de882f528b32e810e + - id: 643fd856d66b6528195ee2cc + cmsLocaleIds: + - 653ad57de882f528b32e810e + response: + body: + publishedItemIds: + - 643fd856d66b6528195ee2ca + - 643fd856d66b6528195ee2cb + errors: + - Staging item ID 643fd856d66b6528195ee2cf not found. + - name: MultipleLocales + path-parameters: + collection_id: 580e63fc8c9a982ac9b8b745 + request: + items: + - id: 643fd856d66b6528195ee2ca + cmsLocaleIds: + - 653ad57de882f528b32e810e + - 6514390aea353fc691d69827 + - 65143930ea353fc691d69cd8 response: body: publishedItemIds: diff --git a/.mock/definition/comments.yml b/.mock/definition/comments.yml new file mode 100644 index 0000000..573e375 --- /dev/null +++ b/.mock/definition/comments.yml @@ -0,0 +1,41 @@ +imports: + root: __package__.yml +webhooks: + comment_created: + audiences: [] + method: POST + display-name: New Comment Thread + headers: {} + payload: root.Comment + examples: + - payload: + triggerType: comment_created + payload: + threadId: 679d2ddb5196117ad04d1ffa + commentId: 679d2ddb5196117ad04d1ff8 + type: new_comment + siteId: 679826b3b20b045e176bc4b5 + pageId: 679826b3b20b045e176bc4bc + localeId: 67993753d910db250db64b3e + itemId: 580e64008c9a982ac9b8b754 + breakpoint: main + url: >- + https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ffa&pageId=679826b3b20b045e176bc4bc + content: 'This comment mentions another user [[6287ec36a841b25637c663df]] ' + isResolved: false + author: + userId: 6287ec36a841b25637c663df + email: ford.prefect@heartofgold.spaceship + name: Ford Prefect + mentionedUsers: + - userId: 6287ec36a841b25637c663df + email: arthur.dent@heartofgold.spaceship + name: Arthur Dent + createdOn: '2025-01-31T20:08:59.759Z' + lastUpdated: '2025-01-31T20:08:59.759Z' + docs: | + Information about a new comment thread or reply + + + There may be a delay of up to 5 minutes before new comments appear in the system and trigger the webhook notification. + diff --git a/.mock/definition/components.yml b/.mock/definition/components.yml index b9eb7d6..3370a4f 100644 --- a/.mock/definition/components.yml +++ b/.mock/definition/components.yml @@ -7,7 +7,9 @@ service: list: path: /sites/{site_id}/components method: GET - auth: true + auth: + - OAuth2: + - components:read docs: | List of all components for a site. @@ -22,17 +24,21 @@ service: request: name: ComponentsListRequest query-parameters: + branchId: + type: optional + docs: Scope the operation to work on a specific branch. limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records response: docs: Request was successful type: root.ComponentList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -42,6 +48,10 @@ service: examples: - path-parameters: site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + branchId: 68026fa68ef6dc744c75b833 + limit: 1 + offset: 1 response: body: components: @@ -74,10 +84,13 @@ service: get-content: path: /sites/{site_id}/components/{component_id}/dom method: GET - auth: true + auth: + - OAuth2: + - components:read docs: > Get static content from a component definition. This includes text - nodes, image nodes and nested component instances. + nodes, image nodes, select nodes, text input nodes, submit button nodes, + and nested component instances. To retrieve dynamic content set by component properties, use the [get component @@ -106,20 +119,27 @@ service: query-parameters: localeId: type: optional - docs: >- - Unique identifier for a specific locale. Applicable, when using - localization. + docs: > + Unique identifier for a specific Locale. + + + [Lear more about + localization.](/data/v2.0.0/docs/working-with-localization) + branchId: + type: optional + docs: Scope the operation to work on a specific branch. limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records response: docs: Request was successful type: root.ComponentDom + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -127,80 +147,66 @@ service: - root.TooManyRequestsError - root.InternalServerError examples: - - name: ComponentDOM - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - response: - body: - componentId: 69118560-d0bc-15fc-bbf8-b8fe5f6535b5 - nodes: - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad623 - componentId: nodes - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad627 - componentId: nodes - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad629 - componentId: nodes - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad631 - componentId: 6258612d1ee792848f805dcf - propertyOverrides: - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad633 - type: Plain Text - text: - text: Don't Panic! - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad635 - type: Rich Text - text: - html:

Always know where your towel is.

- pagination: - limit: 4 - offset: 0 - total: 4 - - name: LocalizedComponentDOM - path-parameters: + - path-parameters: site_id: 580e63e98c9a982ac9b8b741 component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b query-parameters: localeId: 65427cf400e02b306eaa04a0 + branchId: 68026fa68ef6dc744c75b833 + limit: 1 + offset: 1 response: body: componentId: 69118560-d0bc-15fc-bbf8-b8fe5f6535b5 nodes: - - type: component-instance - id: 69118560-d0bc-15fc-bbf8-b8fe5f6535b8 - componentId: nodes + - id: id + text: {} + attributes: + key: value + type: text + - id: id + text: {} + attributes: + key: value + type: text + - id: id + image: {} + attributes: + key: value + type: image + - id: id + placeholder: placeholder + attributes: + key: value + type: text-input + - id: id + choices: + - value: value + text: text + attributes: + key: value + type: select + - id: id + value: value + waitingText: waitingText + attributes: + key: value + type: submit-button + - id: id + componentId: componentId propertyOverrides: - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: 8ebfb409-7493-3bca-5d48-0e547befb960 - componentId: nodes - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: 69118560-d0bc-15fc-bbf8-b8fe5f6535c2 - componentId: 69118560-d0bc-15fc-bbf8-b8fe5f6535b5 - propertyOverrides: - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad623 + type: component-instance pagination: - limit: 100 + limit: 7 offset: 0 - total: 3 + total: 7 update-content: path: /sites/{site_id}/components/{component_id}/dom method: POST - auth: true + auth: + - OAuth2: + - components:write docs: > This endpoint updates content within a component defintion for **secondary locales**. It supports updating up to 1000 nodes in a single @@ -211,13 +217,18 @@ service: 1. Use the [get component content](/data/reference/pages-and-components/components/get-content) - endpoint to identify available content nodes and their types + endpoint to identify available content nodes and their types. 2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) - endpoint + endpoint. + + 3. DOM elements may include a `data-w-id` attribute. This attribute is + used by Webflow to maintain custom attributes and links across locales. + Always include the original `data-w-id` value in your update requests to + ensure consistent behavior across all locales. @@ -241,9 +252,15 @@ service: query-parameters: localeId: type: optional - docs: >- - Unique identifier for a specific locale. Applicable, when using - localization. + docs: > + Unique identifier for a specific Locale. + + + [Lear more about + localization.](/data/v2.0.0/docs/working-with-localization) + branchId: + type: optional + docs: Scope the operation to work on a specific branch. body: properties: nodes: @@ -255,6 +272,7 @@ service: response: docs: Request was successful type: ComponentsUpdateContentResponse + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -268,6 +286,7 @@ service: component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b query-parameters: localeId: 65427cf400e02b306eaa04a0 + branchId: 68026fa68ef6dc744c75b833 request: nodes: - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad623 @@ -276,6 +295,17 @@ service: text: >-

Don't Panic!

Always know where your towel is.

+ - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad635 + choices: + - value: choice-1 + text: First choice + - value: choice-2 + text: Second choice + - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad642 + placeholder: Enter something here... + - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad671 + value: Submit + waitingText: Submitting... - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad629 propertyOverrides: - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 @@ -289,12 +319,14 @@ service: get-properties: path: /sites/{site_id}/components/{component_id}/properties method: GET - auth: true + auth: + - OAuth2: + - components:read docs: > - Get the property default values of a component definition. + Get the default property values of a component definition. - If you do not provide a Locale ID in your request, the response + If you do not include a `localeId` in your request, the response will return any properties that can be localized from the Primary locale. @@ -315,20 +347,27 @@ service: query-parameters: localeId: type: optional - docs: >- - Unique identifier for a specific locale. Applicable, when using - localization. + docs: > + Unique identifier for a specific Locale. + + + [Lear more about + localization.](/data/v2.0.0/docs/working-with-localization) + branchId: + type: optional + docs: Scope the operation to work on a specific branch. limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records response: docs: Request was successful type: root.ComponentProperties + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -341,6 +380,9 @@ service: component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b query-parameters: localeId: 65427cf400e02b306eaa04a0 + branchId: 68026fa68ef6dc744c75b833 + limit: 1 + offset: 1 response: body: componentId: 658205daa3e8206a523b5ad4 @@ -364,9 +406,11 @@ service: update-properties: path: /sites/{site_id}/components/{component_id}/properties method: POST - auth: true + auth: + - OAuth2: + - components:write docs: > - Update the property default values of a component definition in a + Update the default property values of a component definition in a specificed locale. @@ -374,10 +418,16 @@ service: 1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) - endpoint to identify available properties + endpoint to identify properties that can be updated in a secondary + locale. + 2. Rich Text properties may include a `data-w-id` attribute. This + attribute is used by Webflow to maintain links across locales. Always + include the original `data-w-id` value in your update requests to ensure + consistent behavior across all locales. - The request requires a secondary locale ID. If a locale is + + The request requires a secondary locale ID. If a `localeId` is missing, the request will not be processed and will result in an error. @@ -398,9 +448,15 @@ service: query-parameters: localeId: type: optional - docs: >- - Unique identifier for a specific locale. Applicable, when using - localization. + docs: > + Unique identifier for a specific Locale. + + + [Lear more about + localization.](/data/v2.0.0/docs/working-with-localization) + branchId: + type: optional + docs: Scope the operation to work on a specific branch. body: properties: properties: @@ -412,6 +468,7 @@ service: response: docs: Request was successful type: ComponentsUpdatePropertiesResponse + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -424,6 +481,7 @@ service: component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b query-parameters: localeId: 65427cf400e02b306eaa04a0 + branchId: 68026fa68ef6dc744c75b833 request: properties: - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad623 @@ -442,8 +500,12 @@ types: ComponentDomWriteNodesItem: discriminated: false union: - - root.TextNodeWrite - - root.ComponentInstanceNodePropertyOverridesWrite + - type: root.TextNodeWrite + - type: root.ComponentInstanceNodePropertyOverridesWrite + - type: root.Select + - type: root.TextInputNodeWrite + - type: root.SubmitButtonNodeWrite + - type: root.SearchButtonNodeWrite source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true diff --git a/.mock/definition/ecommerce.yml b/.mock/definition/ecommerce.yml index 1a2ca95..426869f 100644 --- a/.mock/definition/ecommerce.yml +++ b/.mock/definition/ecommerce.yml @@ -7,7 +7,9 @@ service: get-settings: path: /sites/{site_id}/ecommerce/settings method: GET - auth: true + auth: + - OAuth2: + - ecommerce:read docs: | Retrieve ecommerce settings for a site. @@ -22,6 +24,7 @@ service: response: docs: Request was successful type: root.EcommerceSettings + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError diff --git a/.mock/definition/forms.yml b/.mock/definition/forms.yml index 9eac177..08f2926 100644 --- a/.mock/definition/forms.yml +++ b/.mock/definition/forms.yml @@ -7,7 +7,9 @@ service: list: path: /sites/{site_id}/forms method: GET - auth: true + auth: + - OAuth2: + - forms:read docs: | List forms for a given site. @@ -23,16 +25,17 @@ service: name: FormsListRequest query-parameters: limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records response: docs: Request was successful type: root.FormList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -44,6 +47,9 @@ service: examples: - path-parameters: site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + limit: 1 + offset: 1 response: body: forms: @@ -53,13 +59,16 @@ service: fields: '0': displayName: Email + placeholder: Enter your email userVisible: true '1': displayName: Email + placeholder: Enter your email userVisible: true responseSettings: redirectUrl: https://example.com redirectMethod: GET + redirectAction: POST https://example.com sendEmailConfirmation: true id: 589a331aa51e760df7ccb89e siteId: 580e63e98c9a982ac9b8b741 @@ -74,10 +83,12 @@ service: fields: '0': displayName: Email + placeholder: Enter your email userVisible: true responseSettings: redirectUrl: https://example.com redirectMethod: GET + redirectAction: POST https://example.com sendEmailConfirmation: false id: 580ff8d7ba3e45ba9fe588e9 siteId: 580e63e98c9a982ac9b8b741 @@ -93,7 +104,9 @@ service: get: path: /forms/{form_id} method: GET - auth: true + auth: + - OAuth2: + - forms:read docs: | Get information about a given form. @@ -108,6 +121,7 @@ service: response: docs: Request was successful type: root.Form + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -149,10 +163,18 @@ service: list-submissions: path: /forms/{form_id}/submissions method: GET - auth: true + auth: + - OAuth2: + - forms:read docs: | List form submissions for a given form + + When a form is used in a component definition, each instance of the form is considered a unique form. + + To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. + + Required scope | `forms:read` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -165,16 +187,17 @@ service: name: FormsListSubmissionsRequest query-parameters: offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' response: docs: Request was successful type: root.FormSubmissionList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -185,6 +208,9 @@ service: examples: - path-parameters: form_id: 580e63e98c9a982ac9b8b741 + query-parameters: + offset: 1 + limit: 1 response: body: formSubmissions: @@ -211,7 +237,9 @@ service: get-submission: path: /form_submissions/{form_submission_id} method: GET - auth: true + auth: + - OAuth2: + - forms:read docs: | Get information about a given form submissio. @@ -226,6 +254,7 @@ service: response: docs: Request was successful type: root.FormSubmission + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -246,10 +275,41 @@ service: formResponse: First Name: Arthur Last Name: Dent + delete-submission: + path: /form_submissions/{form_submission_id} + method: DELETE + auth: + - OAuth2: + - forms:write + docs: | + Delete a form submission + + + Required scope | `forms:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + form_submission_id: + type: string + docs: Unique identifier for a Form Submission + display-name: Delete Form Submission + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + form_submission_id: 580e63e98c9a982ac9b8b741 update-submission: path: /form_submissions/{form_submission_id} method: PATCH - auth: true + auth: + - OAuth2: + - forms:write docs: | Update hidden fields on a form submission @@ -274,6 +334,7 @@ service: response: docs: Request was successful type: root.FormSubmission + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -300,3 +361,39 @@ service: openapi: ../../../openapi/referenced-specs/v2.yml display-name: Forms docs: Forms are forms that are created on your Webflow site. +webhooks: + form_submission: + audiences: [] + method: POST + display-name: Form Submission + headers: {} + payload: root.FormSubmissionTrigger + examples: + - payload: + triggerType: form_submission + payload: + name: Contact Us + siteId: 65427cf400e02b306eaa049c + data: + First Name: Zaphod + Last Name: Beeblebrox + email: zaphod@heartofgold.ai + Phone Number: 15550000000 + schema: + - fieldName: First Name + fieldType: FormTextInput + fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c4 + - fieldName: Last Name + fieldType: FormTextInput + fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c5 + - fieldName: email + fieldType: FormTextInput + fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c6 + - fieldName: Phone Number + fieldType: FormTextInput + fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c7 + submittedAt: '2022-09-14T12:35:16.117Z' + id: 6321ca84df3949bfc6752327 + formId: 65429eadebe8a9f3a30f62d0 + formElementId: 4e038d2c-6a1e-4953-7be9-a59a2b453177 + docs: Information about a form that was subitted diff --git a/.mock/definition/inventory.yml b/.mock/definition/inventory.yml index 5e69c29..139fa04 100644 --- a/.mock/definition/inventory.yml +++ b/.mock/definition/inventory.yml @@ -5,9 +5,11 @@ service: base-path: '' endpoints: list: - path: /collections/{collection_id}/items/{item_id}/inventory + path: /collections/{sku_collection_id}/items/{sku_id}/inventory method: GET - auth: true + auth: + - OAuth2: + - ecommerce:read docs: | List the current inventory levels for a particular SKU item. @@ -15,16 +17,19 @@ service: source: openapi: ../../../openapi/referenced-specs/v2.yml path-parameters: - collection_id: + sku_collection_id: type: string - docs: Unique identifier for a Collection - item_id: + docs: >- + Unique identifier for a SKU collection. Use the List Collections API + to find this ID. + sku_id: type: string - docs: Unique identifier for an Item + docs: Unique identifier for a SKU display-name: List Inventory response: docs: Request was successful type: root.InventoryItem + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -35,17 +40,19 @@ service: - root.InternalServerError examples: - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - item_id: 580e64008c9a982ac9b8b754 + sku_collection_id: 6377a7c4b7a79608c34a46f7 + sku_id: 5e8518516e147040726cc415 response: body: id: 5bfedb42bab0ad90fa7dad39 quantity: 100 inventoryType: finite update: - path: /collections/{collection_id}/items/{item_id}/inventory + path: /collections/{sku_collection_id}/items/{sku_id}/inventory method: PATCH - auth: true + auth: + - OAuth2: + - ecommerce:write docs: > Updates the current inventory levels for a particular SKU item. @@ -64,12 +71,14 @@ service: source: openapi: ../../../openapi/referenced-specs/v2.yml path-parameters: - collection_id: + sku_collection_id: type: string - docs: Unique identifier for a Collection - item_id: + docs: >- + Unique identifier for a SKU collection. Use the List Collections API + to find this ID. + sku_id: type: string - docs: Unique identifier for an Item + docs: Unique identifier for a SKU display-name: Update Item Inventory request: name: InventoryUpdateRequest @@ -88,6 +97,7 @@ service: response: docs: Request was successful type: root.InventoryItem + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -98,8 +108,8 @@ service: - root.InternalServerError examples: - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - item_id: 580e64008c9a982ac9b8b754 + sku_collection_id: 6377a7c4b7a79608c34a46f7 + sku_id: 5e8518516e147040726cc415 request: inventoryType: infinite response: @@ -120,3 +130,23 @@ types: inline: true source: openapi: ../../../openapi/referenced-specs/v2.yml + EcommInventoryChangedPayload: + properties: + triggerType: optional> + payload: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml +webhooks: + ecomm_inventory_changed: + audiences: [] + method: POST + display-name: Updated eComm Inventory + headers: {} + payload: EcommInventoryChangedPayload + examples: + - name: WebhookInventoryChanged + payload: + triggerType: ecomm_inventory_changed + payload: + \$ref: ./schemas/inventory.yml#/InventoryItem/example + docs: Information about updated ecommerce inventory values diff --git a/.mock/definition/items.yml b/.mock/definition/items.yml new file mode 100644 index 0000000..634f1f7 --- /dev/null +++ b/.mock/definition/items.yml @@ -0,0 +1,112 @@ +imports: + root: __package__.yml +webhooks: + collection_item_created: + audiences: [] + method: POST + display-name: Collection Item Created + headers: {} + payload: root.CollectionItemCreated + examples: + - payload: + triggerType: collection_item_created + payload: + id: 580e64008c9a982ac9b8b754 + workspaceId: 625860a7a6c16d624927122f + siteId: 65427cf400e02b306eaa049c + collectionId: 664243617fcc8b464b23c4ee + lastPublished: '2023-03-17T18:47:35Z' + lastUpdated: '2023-03-17T18:47:35Z' + createdOn: '2023-03-17T18:47:35Z' + isArchived: false + isDraft: false + fieldData: + name: Pan-Galactic Gargle Blaster + slug: pan-galactic-gargle-blaster + docs: Information about a new collection item + collection_item_changed: + audiences: [] + method: POST + display-name: Collection Item Updated + headers: {} + payload: root.CollectionItemChanged + examples: + - payload: + triggerType: collection_item_changed + payload: + id: id + workspaceId: workspaceId + siteId: siteId + collectionId: collectionId + fieldData: + name: name + slug: slug + docs: Information about an updated collection item + collection_item_deleted: + audiences: [] + method: POST + display-name: Collection Item Deleted + headers: {} + payload: root.CollectionItemRemoved + examples: + - payload: + triggerType: collection_item_deleted + payload: + id: 66424365e972c886137a1cf1 + siteId: 65427cf400e02b306eaa049c + workspaceId: 625860a7a6c16d624927122f + collectionId: 664243617fcc8b464b23c4ee + cmsLocaleId: 681442a144bb80bd00480fda + lastUpdated: '2025-05-28T04:44:33Z' + createdOn: '2025-05-28T04:27:12Z' + isArchived: false + isDraft: false + fieldData: + name: Earth + slug: earth + description: Mostly harmless + color: '#0000FF' + type: planet + galaxy: Milky Way + docs: Information about a deleted collection item + collection_item_published: + audiences: [] + method: POST + display-name: Collection Item Published + headers: {} + payload: root.CollectionItemPublished + examples: + - payload: + triggerType: collection_item_published + payload: + id: 6321ca84df3949bfc6752327 + siteId: 65427cf400e02b306eaa049c + workspaceId: 625860a7a6c16d624927122f + collectionId: 664243617fcc8b464b23c4ee + cmsLocaleId: 681442a144bb80bd00480fda + docs: Information about a collection item that was published + collection_item_unpublished: + audiences: [] + method: POST + display-name: Collection Item Unpublished + headers: {} + payload: root.CollectionItemUnpublished + examples: + - payload: + triggerType: collection_item_unpublished + payload: + id: 66424365e972c886137a1cf1 + siteId: 65427cf400e02b306eaa049c + workspaceId: 625860a7a6c16d624927122f + collectionId: 664243617fcc8b464b23c4ee + cmsLocaleId: 681442a144bb80bd00480fda + lastUpdated: '2025-05-28T04:44:33Z' + createdOn: '2025-05-28T04:27:12Z' + isArchived: false + isDraft: false + fieldData: + name: Anna Gunn + slug: anna-gunn + _locale: 681442a144bb80bd00480fda + _noSearch: false + docs: Information about a collection item that was removed from the live site diff --git a/.mock/definition/orders.yml b/.mock/definition/orders.yml index b2802cf..1f9711e 100644 --- a/.mock/definition/orders.yml +++ b/.mock/definition/orders.yml @@ -28,7 +28,9 @@ service: list: path: /sites/{site_id}/orders method: GET - auth: true + auth: + - OAuth2: + - ecommerce:read docs: | List all orders created for a given site. @@ -47,16 +49,17 @@ service: type: optional docs: Filter the orders by status offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' response: docs: Request was successful type: root.OrderList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -68,6 +71,10 @@ service: examples: - path-parameters: site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + status: pending + offset: 1 + limit: 1 response: body: orders: @@ -89,15 +96,15 @@ service: customerPaid: unit: USD value: '5892' - string: ' 211.55 USD' + string: \$ 211.55 USD netAmount: unit: USD value: '5892' - string: ' 200.89 USD' + string: \$ 200.89 USD applicationFee: unit: USD value: '5892' - string: ' 4.23 USD' + string: \$ 4.23 USD allAddresses: - type: billing addressee: Arthur Dent @@ -145,7 +152,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 111.22 USD' + string: \$ 111.22 USD productId: 66072fb61b89448912e26791 productName: Luxurious Fresh Ball productSlug: luxurious-fresh-ball @@ -155,11 +162,11 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD weight: 11 width: 82 height: 70 @@ -168,7 +175,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 83.09 USD' + string: \$ 83.09 USD productId: 66072fb61b89448912e2678b productName: Incredible Bronze Towels productSlug: incredible-bronze-towels @@ -180,20 +187,23 @@ service: variantSKU: incredible-bronze-towels-sleek-frozen-incredible-metal variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg variantPrice: unit: USD value: '5892' - string: ' 83.09 USD' + string: \$ 83.09 USD + weight: 5 width: 19 height: 72 length: 18 purchasedItemsCount: 3 stripeDetails: + subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn paymentMethod: pm_1P410gJYFi4lcbXWbeKghqjK paymentIntentId: pi_3P410iJYFi4lcbXW0EKKgcVg customerId: cus_Ptod8KJBiiPgnH chargeId: ch_3P410iJYFi4lcbXW0DxUkzCH + refundReason: requested_by_customer stripeCard: last4: '4242' brand: Visa @@ -224,7 +234,7 @@ service: price: unit: USD value: '5892' - string: '3.44' + string: \$3.44 downloadFiles: - id: 5e9a5eba75e0ac242e1b6f64 name: The modern web design process - Webflow Ebook.pdf @@ -243,15 +253,15 @@ service: customerPaid: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD netAmount: unit: USD value: '5892' - string: ' 112.62 USD' + string: \$ 112.62 USD applicationFee: unit: USD value: '5892' - string: ' 2.37 USD' + string: \$ 2.37 USD allAddresses: - type: billing addressee: Arthur Dent @@ -298,7 +308,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD productId: 66072fb61b89448912e26791 productName: Luxurious Fresh Ball productSlug: luxurious-fresh-ball @@ -308,11 +318,11 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD weight: 11 width: 82 height: 70 @@ -321,7 +331,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD productId: 66072fb61b89448912e26799 productName: Recycled Steel Gloves productSlug: recycled-steel-gloves @@ -335,17 +345,18 @@ service: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD weight: 38 width: 76 height: 85 length: 40 purchasedItemsCount: 2 stripeDetails: + subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft customerId: cus_PpRsNHwWdUoRKR @@ -378,7 +389,7 @@ service: subtotal: unit: USD value: '5892' - string: ' 109.05 USD' + string: \$ 109.05 USD extras: - type: tax name: State Taxes @@ -386,25 +397,25 @@ service: price: unit: USD value: '5892' - string: ' 4.36 USD' + string: \$ 4.36 USD - type: tax name: City Taxes description: NEW YORK Taxes (4.88%) price: unit: USD value: '5892' - string: ' 5.32 USD' + string: \$ 5.32 USD - type: shipping name: Flat description: '' price: unit: USD value: '5892' - string: ' 0.00 USD' + string: \$ 0.00 USD total: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD downloadFiles: - id: 5e9a5eba75e0ac242e1b6f64 name: New product guide @@ -417,7 +428,9 @@ service: get: path: /sites/{site_id}/orders/{order_id} method: GET - auth: true + auth: + - OAuth2: + - ecommerce:read docs: | Retrieve a single product by its ID. All of its SKUs will also be retrieved. @@ -436,6 +449,7 @@ service: response: docs: Request was successful type: root.Order + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -468,15 +482,15 @@ service: customerPaid: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD netAmount: unit: USD value: '5892' - string: ' 112.62 USD' + string: \$ 112.62 USD applicationFee: unit: USD value: '5892' - string: ' 2.37 USD' + string: \$ 2.37 USD allAddresses: - type: billing japanType: kana @@ -527,7 +541,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD productId: 66072fb61b89448912e26791 productName: Luxurious Fresh Ball productSlug: luxurious-fresh-ball @@ -537,11 +551,11 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD weight: 11 width: 82 height: 70 @@ -550,7 +564,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD productId: 66072fb61b89448912e26799 productName: Recycled Steel Gloves productSlug: recycled-steel-gloves @@ -560,11 +574,11 @@ service: variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD weight: 38 width: 76 height: 85 @@ -605,7 +619,7 @@ service: subtotal: unit: USD value: '5892' - string: ' 109.05 USD' + string: \$ 109.05 USD extras: - type: tax name: State Taxes @@ -613,25 +627,25 @@ service: price: unit: USD value: '5892' - string: ' 4.36 USD' + string: \$ 4.36 USD - type: tax name: City Taxes description: NEW YORK Taxes (4.88%) price: unit: USD value: '5892' - string: ' 5.32 USD' + string: \$ 5.32 USD - type: shipping name: Flat description: '' price: unit: USD value: '5892' - string: ' 0.00 USD' + string: \$ 0.00 USD total: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD downloadFiles: - id: 5e9a5eba75e0ac242e1b6f64 name: New product guide @@ -640,7 +654,9 @@ service: update: path: /sites/{site_id}/orders/{order_id} method: PATCH - auth: true + auth: + - OAuth2: + - ecommerce:write docs: | This API lets you update the fields, `comment`, `shippingProvider`, and/or `shippingTracking` for a given order. All three fields can be @@ -677,6 +693,7 @@ service: response: docs: Request was successful type: root.Order + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -710,15 +727,15 @@ service: customerPaid: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD netAmount: unit: USD value: '5892' - string: ' 112.62 USD' + string: \$ 112.62 USD applicationFee: unit: USD value: '5892' - string: ' 2.37 USD' + string: \$ 2.37 USD allAddresses: - type: billing japanType: kana @@ -769,7 +786,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD productId: 66072fb61b89448912e26791 productName: Luxurious Fresh Ball productSlug: luxurious-fresh-ball @@ -779,11 +796,11 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD weight: 11 width: 82 height: 70 @@ -792,7 +809,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD productId: 66072fb61b89448912e26799 productName: Recycled Steel Gloves productSlug: recycled-steel-gloves @@ -802,11 +819,11 @@ service: variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD weight: 38 width: 76 height: 85 @@ -847,7 +864,7 @@ service: subtotal: unit: USD value: '5892' - string: ' 109.05 USD' + string: \$ 109.05 USD extras: - type: tax name: State Taxes @@ -855,25 +872,25 @@ service: price: unit: USD value: '5892' - string: ' 4.36 USD' + string: \$ 4.36 USD - type: tax name: City Taxes description: NEW YORK Taxes (4.88%) price: unit: USD value: '5892' - string: ' 5.32 USD' + string: \$ 5.32 USD - type: shipping name: Flat description: '' price: unit: USD value: '5892' - string: ' 0.00 USD' + string: \$ 0.00 USD total: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD downloadFiles: - id: 5e9a5eba75e0ac242e1b6f64 name: New product guide @@ -882,7 +899,9 @@ service: update-fulfill: path: /sites/{site_id}/orders/{order_id}/fulfill method: POST - auth: true + auth: + - OAuth2: + - ecommerce:write docs: | Updates an order's status to fulfilled @@ -909,6 +928,7 @@ service: response: docs: Request was successful type: root.Order + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -942,15 +962,15 @@ service: customerPaid: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD netAmount: unit: USD value: '5892' - string: ' 112.62 USD' + string: \$ 112.62 USD applicationFee: unit: USD value: '5892' - string: ' 2.37 USD' + string: \$ 2.37 USD allAddresses: - type: billing japanType: kana @@ -1001,7 +1021,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD productId: 66072fb61b89448912e26791 productName: Luxurious Fresh Ball productSlug: luxurious-fresh-ball @@ -1011,11 +1031,11 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD weight: 11 width: 82 height: 70 @@ -1024,7 +1044,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD productId: 66072fb61b89448912e26799 productName: Recycled Steel Gloves productSlug: recycled-steel-gloves @@ -1034,11 +1054,11 @@ service: variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD weight: 38 width: 76 height: 85 @@ -1079,7 +1099,7 @@ service: subtotal: unit: USD value: '5892' - string: ' 109.05 USD' + string: \$ 109.05 USD extras: - type: tax name: State Taxes @@ -1087,25 +1107,25 @@ service: price: unit: USD value: '5892' - string: ' 4.36 USD' + string: \$ 4.36 USD - type: tax name: City Taxes description: NEW YORK Taxes (4.88%) price: unit: USD value: '5892' - string: ' 5.32 USD' + string: \$ 5.32 USD - type: shipping name: Flat description: '' price: unit: USD value: '5892' - string: ' 0.00 USD' + string: \$ 0.00 USD total: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD downloadFiles: - id: 5e9a5eba75e0ac242e1b6f64 name: New product guide @@ -1114,7 +1134,9 @@ service: update-unfulfill: path: /sites/{site_id}/orders/{order_id}/unfulfill method: POST - auth: true + auth: + - OAuth2: + - ecommerce:write docs: | Updates an order's status to unfulfilled @@ -1132,6 +1154,7 @@ service: response: docs: Request was successful type: root.Order + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -1164,15 +1187,15 @@ service: customerPaid: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD netAmount: unit: USD value: '5892' - string: ' 112.62 USD' + string: \$ 112.62 USD applicationFee: unit: USD value: '5892' - string: ' 2.37 USD' + string: \$ 2.37 USD allAddresses: - type: billing japanType: kana @@ -1223,7 +1246,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD productId: 66072fb61b89448912e26791 productName: Luxurious Fresh Ball productSlug: luxurious-fresh-ball @@ -1233,11 +1256,11 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD weight: 11 width: 82 height: 70 @@ -1246,7 +1269,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD productId: 66072fb61b89448912e26799 productName: Recycled Steel Gloves productSlug: recycled-steel-gloves @@ -1256,11 +1279,11 @@ service: variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD weight: 38 width: 76 height: 85 @@ -1301,7 +1324,7 @@ service: subtotal: unit: USD value: '5892' - string: ' 109.05 USD' + string: \$ 109.05 USD extras: - type: tax name: State Taxes @@ -1309,25 +1332,25 @@ service: price: unit: USD value: '5892' - string: ' 4.36 USD' + string: \$ 4.36 USD - type: tax name: City Taxes description: NEW YORK Taxes (4.88%) price: unit: USD value: '5892' - string: ' 5.32 USD' + string: \$ 5.32 USD - type: shipping name: Flat description: '' price: unit: USD value: '5892' - string: ' 0.00 USD' + string: \$ 0.00 USD total: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD downloadFiles: - id: 5e9a5eba75e0ac242e1b6f64 name: New product guide @@ -1336,7 +1359,9 @@ service: refund: path: /sites/{site_id}/orders/{order_id}/refund method: POST - auth: true + auth: + - OAuth2: + - ecommerce:write docs: | This API will reverse a Stripe charge and refund an order back to a customer. It will also set the order's status to `refunded`. @@ -1363,6 +1388,7 @@ service: response: docs: Request was successful type: root.Order + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -1396,15 +1422,15 @@ service: customerPaid: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD netAmount: unit: USD value: '5892' - string: ' 112.62 USD' + string: \$ 112.62 USD applicationFee: unit: USD value: '5892' - string: ' 2.37 USD' + string: \$ 2.37 USD allAddresses: - type: billing japanType: kana @@ -1455,7 +1481,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD productId: 66072fb61b89448912e26791 productName: Luxurious Fresh Ball productSlug: luxurious-fresh-ball @@ -1465,11 +1491,11 @@ service: variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg variantPrice: unit: USD value: '5892' - string: ' 55.61 USD' + string: \$ 55.61 USD weight: 11 width: 82 height: 70 @@ -1478,7 +1504,7 @@ service: rowTotal: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD productId: 66072fb61b89448912e26799 productName: Recycled Steel Gloves productSlug: recycled-steel-gloves @@ -1488,11 +1514,11 @@ service: variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey variantImage: url: >- - https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg variantPrice: unit: USD value: '5892' - string: ' 53.44 USD' + string: \$ 53.44 USD weight: 38 width: 76 height: 85 @@ -1533,7 +1559,7 @@ service: subtotal: unit: USD value: '5892' - string: ' 109.05 USD' + string: \$ 109.05 USD extras: - type: tax name: State Taxes @@ -1541,25 +1567,25 @@ service: price: unit: USD value: '5892' - string: ' 4.36 USD' + string: \$ 4.36 USD - type: tax name: City Taxes description: NEW YORK Taxes (4.88%) price: unit: USD value: '5892' - string: ' 5.32 USD' + string: \$ 5.32 USD - type: shipping name: Flat description: '' price: unit: USD value: '5892' - string: ' 0.00 USD' + string: \$ 0.00 USD total: unit: USD value: '5892' - string: ' 118.73 USD' + string: \$ 118.73 USD downloadFiles: - id: 5e9a5eba75e0ac242e1b6f64 name: New product guide @@ -1569,3 +1595,377 @@ service: openapi: ../../../openapi/referenced-specs/v2.yml display-name: Orders docs: Orders are the orders for your Webflow site. +webhooks: + ecomm_new_order: + audiences: [] + method: POST + display-name: New eComm Order + headers: {} + payload: root.NewOrder + examples: + - payload: + triggerType: ecomm_new_order + payload: + orderId: fc7-128 + status: unfulfilled + comment: >- + Customer requested gift wrapping and a personalized note saying: + Happy Birthday, Ford! 🎉 Please ensure the item is packed with + extra bubble wrap for safe transit. + orderComment: >- + Please gift wrap with a personal note saying "Happy Birthday, + Ford! 🎉 + acceptedOn: '2024-03-29T21:29:21Z' + fulfilledOn: '2018-12-03T22:06:15Z' + refundedOn: '2018-12-03T22:06:15Z' + disputedOn: '2018-12-03T22:06:15Z' + disputeUpdatedOn: '2018-12-03T22:06:15Z' + customerPaid: + unit: USD + value: '5892' + string: \$ 118.73 USD + netAmount: + unit: USD + value: '5892' + string: \$ 112.62 USD + applicationFee: + unit: USD + value: '5892' + string: \$ 2.37 USD + allAddresses: + - type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + - type: shipping + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingAddress: + type: shipping + japanType: kanji + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + billingAddress: + type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingProvider: Shipping Company, Co. + shippingTracking: tr00000000001 + shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 + customerInfo: + fullName: Arthur Dent + email: arthur.dent@example.com + purchasedItems: + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: \$ 55.61 USD + productId: 66072fb61b89448912e26791 + productName: Luxurious Fresh Ball + productSlug: luxurious-fresh-ball + variantId: 66072fb71b89448912e2683f + variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' + variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic + variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic + variantImage: + url: >- + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + variantPrice: + unit: USD + value: '5892' + string: \$ 55.61 USD + weight: 11 + width: 82 + height: 70 + length: 9 + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: \$ 53.44 USD + productId: 66072fb61b89448912e26799 + productName: Recycled Steel Gloves + productSlug: recycled-steel-gloves + variantId: 66072fb91b89448912e26ab9 + variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' + variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantImage: + url: >- + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + variantPrice: + unit: USD + value: '5892' + string: \$ 53.44 USD + weight: 38 + width: 76 + height: 85 + length: 40 + purchasedItemsCount: 2 + stripeDetails: + subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn + paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j + paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft + customerId: cus_PpRsNHwWdUoRKR + chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 + refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk + refundReason: fraudulent + stripeCard: + last4: '4242' + brand: Visa + ownerName: Arthur Dent + expires: + year: 2024 + month: 4 + customData: + - key: value + metadata: + isBuyNow: false + isCustomerDeleted: false + isShippingRequired: true + hasDownloads: false + paymentProcessor: stripe + totals: + subtotal: + unit: USD + value: '5892' + string: \$ 109.05 USD + extras: + - type: tax + name: State Taxes + description: NY Taxes (4.00%) + price: + unit: USD + value: '5892' + string: \$ 4.36 USD + - type: tax + name: City Taxes + description: NEW YORK Taxes (4.88%) + price: + unit: USD + value: '5892' + string: \$ 5.32 USD + - type: shipping + name: Flat + description: '' + price: + unit: USD + value: '5892' + string: \$ 0.00 USD + total: + unit: USD + value: '5892' + string: \$ 118.73 USD + downloadFiles: + - id: 5e9a5eba75e0ac242e1b6f64 + name: New product guide + url: >- + https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa + docs: Information about a new ecommerce order + ecomm_order_changed: + audiences: [] + method: POST + display-name: Updated eComm Order + headers: {} + payload: root.UpdatedOrder + examples: + - payload: + triggerType: ecomm_order_changed + payload: + orderId: fc7-128 + status: refunded + comment: >- + Customer requested gift wrapping and a personalized note saying: + Happy Birthday, Ford! 🎉 Please ensure the item is packed with + extra bubble wrap for safe transit. + orderComment: >- + Please gift wrap with a personal note saying "Happy Birthday, + Ford! 🎉 + acceptedOn: '2024-03-29T21:29:21Z' + fulfilledOn: '2024-03-29T21:29:21Z' + refundedOn: '2024-04-08T18:25:04Z' + disputedOn: '2024-03-29T21:29:21Z' + disputeUpdatedOn: '2024-03-29T21:29:21Z' + disputeLastStatus: charge_refunded + customerPaid: + unit: USD + value: '5892' + string: \$ 118.73 USD + netAmount: + unit: USD + value: '5892' + string: \$ 112.62 USD + applicationFee: + unit: USD + value: '5892' + string: \$ 2.37 USD + allAddresses: + - type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + - type: shipping + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingAddress: + type: shipping + japanType: kanji + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + billingAddress: + type: billing + addressee: Arthur Dent + line1: 20 W 34th St + line2: Empire State Building + city: New York + state: New York + country: US + postalCode: '10118' + shippingProvider: Shipping Company, Co. + shippingTracking: tr00000000001 + shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 + customerInfo: + fullName: Arthur Dent + email: arthur.dent@example.com + purchasedItems: + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: \$ 55.61 USD + productId: 66072fb61b89448912e26791 + productName: Luxurious Fresh Ball + productSlug: luxurious-fresh-ball + variantId: 66072fb71b89448912e2683f + variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' + variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic + variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic + variantImage: + url: >- + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg + variantPrice: + unit: USD + value: '5892' + string: \$ 55.61 USD + weight: 11 + width: 82 + height: 70 + length: 9 + - count: 1 + rowTotal: + unit: USD + value: '5892' + string: \$ 53.44 USD + productId: 66072fb61b89448912e26799 + productName: Recycled Steel Gloves + productSlug: recycled-steel-gloves + variantId: 66072fb91b89448912e26ab9 + variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' + variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey + variantImage: + url: >- + https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg + variantPrice: + unit: USD + value: '5892' + string: \$ 53.44 USD + weight: 38 + width: 76 + height: 85 + length: 40 + purchasedItemsCount: 2 + stripeDetails: + subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn + paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j + paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft + customerId: cus_PpRsNHwWdUoRKR + chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 + refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk + refundReason: fraudulent + stripeCard: + last4: '4242' + brand: Visa + ownerName: Arthur Dent + expires: + year: 2024 + month: 4 + customData: + - key: value + metadata: + isBuyNow: false + isCustomerDeleted: false + isShippingRequired: true + hasDownloads: false + paymentProcessor: stripe + totals: + subtotal: + unit: USD + value: '5892' + string: \$ 109.05 USD + extras: + - type: tax + name: State Taxes + description: NY Taxes (4.00%) + price: + unit: USD + value: '5892' + string: \$ 4.36 USD + - type: tax + name: City Taxes + description: NEW YORK Taxes (4.88%) + price: + unit: USD + value: '5892' + string: \$ 5.32 USD + - type: shipping + name: Flat + description: '' + price: + unit: USD + value: '5892' + string: \$ 0.00 USD + total: + unit: USD + value: '5892' + string: \$ 118.73 USD + downloadFiles: + - id: 5e9a5eba75e0ac242e1b6f64 + name: New product guide + url: >- + https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa + docs: Information about an updated ecommerce order diff --git a/.mock/definition/pages.yml b/.mock/definition/pages.yml index 62de7dc..12d954e 100644 --- a/.mock/definition/pages.yml +++ b/.mock/definition/pages.yml @@ -7,7 +7,9 @@ service: list: path: /sites/{site_id}/pages method: GET - auth: true + auth: + - OAuth2: + - page:read docs: | List of all pages for a site. @@ -24,20 +26,24 @@ service: query-parameters: localeId: type: optional - docs: >- - Unique identifier for a specific locale. Applicable, when using - localization. + docs: > + Unique identifier for a specific Locale. + + + [Lear more about + localization.](/data/v2.0.0/docs/working-with-localization) limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records response: docs: Request was successful type: root.PageList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -49,6 +55,8 @@ service: site_id: 580e63e98c9a982ac9b8b741 query-parameters: localeId: 65427cf400e02b306eaa04a0 + limit: 1 + offset: 1 response: body: pages: @@ -62,9 +70,9 @@ service: lastUpdated: '2024-03-11T10:42:42Z' archived: false draft: false - canBranch: true - isBranch: false - isMembersOnly: false + canBranch: false + isBranch: true + branchId: 68026fa68ef6dc744c75b833 seo: title: The Ultimate Hitchhiker's Guide to the Galaxy description: >- @@ -91,7 +99,7 @@ service: draft: false canBranch: true isBranch: false - isMembersOnly: false + branchId: 68026fa68ef6dc744c75b833 seo: title: Celebrate Towel Day - The Hitchhiker's Guide to the Galaxy description: >- @@ -115,7 +123,9 @@ service: get-metadata: path: /pages/{page_id} method: GET - auth: true + auth: + - OAuth2: + - page:read docs: | Get metadata information for a single page. @@ -132,12 +142,16 @@ service: query-parameters: localeId: type: optional - docs: >- - Unique identifier for a specific locale. Applicable, when using - localization. + docs: > + Unique identifier for a specific Locale. + + + [Lear more about + localization.](/data/v2.0.0/docs/working-with-localization) response: docs: Request was successful type: root.Page + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -161,9 +175,9 @@ service: lastUpdated: '2024-03-11T10:42:42Z' archived: false draft: false - canBranch: true - isBranch: false - isMembersOnly: false + canBranch: false + isBranch: true + branchId: 68026fa68ef6dc744c75b833 seo: title: The Ultimate Hitchhiker's Guide to the Galaxy description: >- @@ -181,7 +195,9 @@ service: update-page-settings: path: /pages/{page_id} method: PUT - auth: true + auth: + - OAuth2: + - page:write docs: | Update Page-level metadata, including SEO and Open Graph fields. @@ -194,18 +210,42 @@ service: docs: Unique identifier for a Page display-name: Update Page Metadata request: - body: root.Page + name: PageMetadataWrite query-parameters: localeId: type: optional - docs: >- - Unique identifier for a specific locale. Applicable, when using - localization. - name: UpdatePageSettingsRequest + docs: > + Unique identifier for a specific Locale. + + + [Lear more about + localization.](/data/v2.0.0/docs/working-with-localization) + body: + properties: + title: + type: optional + docs: Title for the page + slug: + type: optional + docs: > + Slug for the page. + + + + **Note:** Updating slugs in secondary locales is only supported + in Advanced and + Enterprise localization add-on plans. + seo: + type: optional + docs: SEO-related fields for the Page + openGraph: + type: optional + docs: Open Graph fields for the Page content-type: application/json response: docs: Request was successful type: root.Page + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -218,16 +258,8 @@ service: query-parameters: localeId: 65427cf400e02b306eaa04a0 request: - id: 6596da6045e56dee495bcbba - siteId: 6258612d1ee792848f805dcf title: Guide to the Galaxy slug: guide-to-the-galaxy - createdOn: '2024-03-11T10:42:00Z' - lastUpdated: '2024-03-11T10:42:42Z' - archived: false - draft: false - canBranch: true - isBranch: false seo: title: The Ultimate Hitchhiker's Guide to the Galaxy description: >- @@ -240,8 +272,6 @@ service: Dive deep into the mysteries of the universe with your guide to everything galactic. descriptionCopied: false - localeId: 653fd9af6a07fc9cfd7a5e57 - publishedPath: /en-us/guide-to-the-galaxy response: body: id: 6596da6045e56dee495bcbba @@ -254,9 +284,9 @@ service: lastUpdated: '2024-03-11T10:42:42Z' archived: false draft: false - canBranch: true - isBranch: false - isMembersOnly: false + canBranch: false + isBranch: true + branchId: 68026fa68ef6dc744c75b833 seo: title: The Ultimate Hitchhiker's Guide to the Galaxy description: >- @@ -274,21 +304,13 @@ service: get-content: path: /pages/{page_id}/dom method: GET - auth: true - docs: > - Get static content from a static page. This includes text nodes, image - nodes and component instances. - - To retrieve the contents of components in the page use the [get - component - content](/data/reference/pages-and-components/components/get-content) - endpoint. - - - If you do not provide a Locale ID in your request, the response - will return any content that can be localized from the Primary - locale. + auth: + - OAuth2: + - page:read + docs: | + Get text and component instance content from a static page. + Localization Required scope | `pages:read` source: @@ -303,20 +325,24 @@ service: query-parameters: localeId: type: optional - docs: >- - Unique identifier for a specific locale. Applicable, when using - localization. + docs: > + Unique identifier for a specific Locale. + + + [Lear more about + localization.](/data/v2.0.0/docs/working-with-localization) limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records response: docs: Request was successful type: root.Dom + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -325,52 +351,65 @@ service: - root.TooManyRequestsError - root.InternalServerError examples: - - name: PageDOM - path-parameters: + - path-parameters: page_id: 63c720f9347c2139b248e552 query-parameters: localeId: 65427cf400e02b306eaa04a0 + limit: 1 + offset: 1 response: body: pageId: 658205daa3e8206a523b5ad4 + branchId: 68026fa68ef6dc744c75b833 nodes: - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad623 - componentId: nodes + - id: id + text: {} + attributes: + key: value + type: text + - id: id + text: {} + attributes: + key: value + type: text + - id: id + image: {} + attributes: + key: value + type: image + - id: id + choices: + - value: value + text: text + attributes: + key: value + type: select + - id: id + placeholder: placeholder + attributes: + key: value + type: text-input + - id: id + text: {} + attributes: + key: value + type: text + - id: id + componentId: componentId propertyOverrides: - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad627 - componentId: nodes - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad629 - componentId: nodes - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - - type: component-instance - id: a245c12d-995b-55ee-5ec7-aa36a6cad631 - componentId: 6258612d1ee792848f805dcf - propertyOverrides: - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad633 - type: Plain Text - label: Catchphrase - text: - text: Don't Panic! - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad635 - type: Rich Text - label: Tagline - text: - html:

Always know where your towel is.

+ type: component-instance pagination: limit: 4 offset: 0 total: 4 + lastUpdated: '2016-10-24T19:42:38Z' update-static-content: path: /pages/{page_id}/dom method: POST - auth: true + auth: + - OAuth2: + - page:write docs: > This endpoint updates content on a static page in **secondary locales**. It supports updating up to 1000 nodes in a single request. @@ -380,12 +419,17 @@ service: 1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) - endpoint to identify available content nodes and their types + endpoint to identify available content nodes and their types. 2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) - endpoint + endpoint. + + 3. DOM elements may include a `data-w-id` attribute. This attribute is + used by Webflow to maintain custom attributes and links across locales. + Always include the original `data-w-id` value in your update requests to + ensure consistent behavior across all locales. @@ -418,6 +462,7 @@ service: response: docs: Request was successful type: UpdateStaticContentResponse + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -438,6 +483,17 @@ service: text: >-

Don't Panic!

Always know where your towel is.

+ - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad635 + choices: + - value: choice-1 + text: First choice + - value: choice-2 + text: Second choice + - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad642 + placeholder: Enter something here... + - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad671 + value: Submit + waitingText: Submitting... - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad629 propertyOverrides: - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 @@ -453,11 +509,47 @@ service: display-name: Pages docs: Pages are the pages in your Webflow site. types: + PageMetadataWriteSeo: + docs: SEO-related fields for the Page + properties: + title: + type: optional + docs: The Page title shown in search engine results + description: + type: optional + docs: The Page description shown in search engine results + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + PageMetadataWriteOpenGraph: + docs: Open Graph fields for the Page + properties: + title: + type: optional + docs: The title supplied to Open Graph annotations + titleCopied: + type: optional + docs: Indicates the Open Graph title was copied from the SEO title + description: + type: optional + docs: The description supplied to Open Graph annotations + descriptionCopied: + type: optional + docs: >- + Indicates the Open Graph description was copied from the SEO + description + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true PageDomWriteNodesItem: discriminated: false union: - - root.TextNodeWrite - - root.ComponentInstanceNodePropertyOverridesWrite + - type: root.TextNodeWrite + - type: root.ComponentInstanceNodePropertyOverridesWrite + - type: root.Select + - type: root.TextInputNodeWrite + - type: root.SubmitButtonNodeWrite + - type: root.SearchButtonNodeWrite source: openapi: ../../../openapi/referenced-specs/v2.yml inline: true @@ -468,3 +560,52 @@ types: type: list source: openapi: ../../../openapi/referenced-specs/v2.yml +webhooks: + page_created: + audiences: [] + method: POST + display-name: Page Created + headers: {} + payload: root.PageCreatedWebhook + examples: + - payload: + triggerType: page_created + payload: + siteId: 65427cf400e02b306eaa049c + pageId: 66a3cfb276641574f5d58311 + pageTitle: Heart of Gold Specs + createdOn: '2024-07-26T16:32:50Z' + publishedPath: /blog/earth + docs: Information about a new pages + page_metadata_updated: + audiences: [] + method: POST + display-name: Page Metadata Updated + headers: {} + payload: root.PageMetadataUpdatedWebhook + examples: + - payload: + triggerType: page_metadata_updated + payload: + siteId: 65427cf400e02b306eaa049c + pageId: 66a3cfb276641574f5d58311 + pageTitle: Heart of Gold Specs + lastUpdated: '2024-07-26T16:32:50Z' + publishedPath: /blog/earth + docs: Information about a page's updated metadata and/or settings + page_deleted: + audiences: [] + method: POST + display-name: Page Deleted + headers: {} + payload: root.PageDeletedWebhook + examples: + - payload: + triggerType: page_deleted + payload: + siteId: 65427cf400e02b306eaa049c + pageId: 66a3cfb276641574f5d58311 + pageTitle: Heart of Gold Specs + deletedOn: '2024-07-26T16:32:50Z' + publishedPath: /blog/earth + docs: Information about a page that was deleted diff --git a/.mock/definition/pages/scripts.yml b/.mock/definition/pages/scripts.yml index f8ee328..59bc96a 100644 --- a/.mock/definition/pages/scripts.yml +++ b/.mock/definition/pages/scripts.yml @@ -7,23 +7,11 @@ service: get-custom-code: path: /pages/{page_id}/custom_code method: GET - auth: true - docs: > - Get all registered scripts that have been applied to a specific Page. - - - In order to use the Custom Code APIs for Sites and Pages, Custom Code - Scripts must first be registered - - to a Site via the `registered_scripts` endpoints, and then applied to a - Site or Page using the appropriate - - `custom_code` endpoints. - - - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). - + auth: + - OAuth2: + - custom_code:read + docs: | + Get all scripts applied to a page. Required scope | `custom_code:read` source: @@ -36,6 +24,7 @@ service: response: docs: Request was successful type: root.ScriptApplyList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -58,25 +47,20 @@ service: upsert-custom-code: path: /pages/{page_id}/custom_code method: PUT - auth: true + auth: + - OAuth2: + - custom_code:write docs: > - Add a registered script to a Page. + Apply registered scripts to a page. If you have multiple scripts your + App needs to apply or maintain on a page, ensure they are always + included in the request body for this endpoint. To remove individual + scripts, simply call this endpoint without the script in the request + body. - In order to use the Custom Code APIs for Sites and Pages, Custom Code - Scripts must first be registered - - to a Site via the `registered_scripts` endpoints, and then applied to a - Site or Page using the appropriate - - `custom_code` endpoints. - - - A site can have a maximum of 800 registered scripts. - - - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + + To apply a script to a page, the script must first be registered to a Site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -93,6 +77,7 @@ service: response: docs: Request was successful type: root.ScriptApplyList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -131,22 +116,22 @@ service: delete-custom-code: path: /pages/{page_id}/custom_code method: DELETE - auth: true + auth: + - OAuth2: + - custom_code:write docs: > - Delete the custom code block that an app has created for a page - - - In order to use the Custom Code APIs for Sites and Pages, Custom Code - Scripts must first be registered + Remove all scripts from a page applied by the App. This endpoint will + not remove scripts from the site's registered scripts. - to a Site via the `registered_scripts` endpoints, and then applied to a - Site or Page using the appropriate - `custom_code` endpoints. + To remove individual scripts applied by the App, use the [Add/Update + Custom + Code](/data/reference/custom-code/custom-code-pages/upsert-custom-code) + endpoint. - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + Access to this endpoint requires a bearer token obtained from an + [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write` diff --git a/.mock/definition/products.yml b/.mock/definition/products.yml index 4c6fcd1..9474978 100644 --- a/.mock/definition/products.yml +++ b/.mock/definition/products.yml @@ -7,7 +7,9 @@ service: list: path: /sites/{site_id}/products method: GET - auth: true + auth: + - OAuth2: + - ecommerce:read docs: > Retrieve all products for a site. @@ -31,16 +33,17 @@ service: name: ProductsListRequest query-parameters: offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' response: docs: Request was successful type: root.ProductAndSkUsList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -52,6 +55,9 @@ service: examples: - path-parameters: site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + offset: 1 + limit: 1 response: body: items: @@ -72,24 +78,34 @@ service: - id: Color name: Color enum: - - id: id + - id: royal-blue name: Royal Blue slug: royal-blue skus: - - id: 580e63fc8c9a982ac9b8b745 + - id: 66072fb71b89448912e2681c cmsLocaleId: 653ad57de882f528b32e810e lastPublished: '2023-03-17T18:47:35Z' lastUpdated: '2023-03-17T18:47:35Z' createdOn: '2023-03-17T18:47:35Z' fieldData: sku-values: - ff42fee0113744f693a764e3431a9cc2: 64a74715c456e36762fc39a1 - name: Blue T-shirt - slug: t-shirt-blue + color: blue + size: small + name: Colorful T-shirt - Default + slug: colorful-t-shirt-default price: - value: 100 + value: 2499 unit: USD - quantity: 10 + currency: USD + main-image: https://www.example.com/image.jpg + sku: '1234567890' + sku-properties: + - id: Color + name: Color + enum: + - id: royal-blue + name: Royal Blue + slug: royal-blue pagination: limit: 100 offset: 0 @@ -97,22 +113,18 @@ service: create: path: /sites/{site_id}/products method: POST - auth: true + auth: + - OAuth2: + - ecommerce:write docs: > - Create a new product and SKU. + Create a new ecommerce product and defaultSKU. A product, at minimum, + must have a single SKU. - When you create a product, you will always create a SKU, since a Product - Item must have, at minimum, a single SKU. - - - To create a Product with multiple SKUs - for example a T-shirt in sizes - small, medium and large: - - Create parameters in `sku-properties`, also known as [product options and variants.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). - - A single `sku-property` would be `color`. Within the `color` property, list the various colors of T-shirts as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. - - Once, you've created a Product and its `sku-properties` with `enum` values, Webflow will create a **default SKU**, which will automatically be a combination of the first `sku-properties` you've created. - - In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. - - After you've created your product, you can create additional SKUs using the [Create SKU endpoint.](/data/reference/ecommerce/products/create-sku) + To create a product with multiple SKUs: + - First, create a list of `sku-properties`, also known as [product options](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). For example, a T-shirt product may have a "color" `sku-property`, with a list of enum values: red, yellow, and blue, another `sku-property` may be "size", with a list of enum values: small, medium, and large. + - Once, a product is created with a list of `sku-properties`, Webflow will create a **default SKU**, which is always a combination of the first `enum` values of each `sku-property`. (e.g. Small - Red - T-Shirt) + - After creation, you can create additional SKUs for the product, using the [Create SKUs endpoint.](/data/reference/ecommerce/products/create-sku) Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the @@ -132,12 +144,13 @@ service: body: properties: publishStatus: optional - product: optional - sku: optional + product: ProductSkuCreateProduct + sku: ProductSkuCreateSku content-type: application/json response: docs: Request was successful type: root.ProductAndSkUs + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -149,7 +162,50 @@ service: examples: - path-parameters: site_id: 580e63e98c9a982ac9b8b741 - request: {} + request: + publishStatus: staging + product: + fieldData: + name: Colorful T-shirt + slug: colorful-t-shirt + description: >- + Our best-selling t-shirt available in multiple colors and + sizes + sku-properties: + - id: color + name: Color + enum: + - id: red + name: Red + slug: red + - id: yellow + name: Yellow + slug: yellow + - id: blue + name: Blue + slug: blue + - id: size + name: Size + enum: + - id: small + name: Small + slug: small + - id: medium + name: Medium + slug: medium + - id: large + name: Large + slug: large + sku: + fieldData: + name: Colorful T-shirt - Red Small + slug: colorful-t-shirt-red-small + price: + value: 2499 + unit: USD + currency: USD + main-image: >- + https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987 response: body: product: @@ -169,33 +225,45 @@ service: - id: Color name: Color enum: - - id: id + - id: royal-blue name: Royal Blue slug: royal-blue - categories: - - categories + category: + - category tax-category: standard-taxable default-sku: default-sku ec-product-type: ff42fee0113744f693a764e3431a9cc2 skus: - - id: 580e63fc8c9a982ac9b8b745 + - id: 66072fb71b89448912e2681c cmsLocaleId: 653ad57de882f528b32e810e lastPublished: '2023-03-17T18:47:35Z' lastUpdated: '2023-03-17T18:47:35Z' createdOn: '2023-03-17T18:47:35Z' fieldData: sku-values: - ff42fee0113744f693a764e3431a9cc2: 64a74715c456e36762fc39a1 - name: Blue T-shirt - slug: t-shirt-blue + color: blue + size: small + name: Colorful T-shirt - Default + slug: colorful-t-shirt-default price: - value: 100 + value: 2499 unit: USD - quantity: 10 + currency: USD + main-image: https://www.example.com/image.jpg + sku: '1234567890' + sku-properties: + - id: Color + name: Color + enum: + - id: royal-blue + name: Royal Blue + slug: royal-blue get: path: /sites/{site_id}/products/{product_id} method: GET - auth: true + auth: + - OAuth2: + - ecommerce:read docs: | Retrieve a single product by its ID. All of its SKUs will also be retrieved. @@ -214,6 +282,7 @@ service: response: docs: Request was successful type: root.ProductAndSkUs + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -245,33 +314,45 @@ service: - id: Color name: Color enum: - - id: id + - id: royal-blue name: Royal Blue slug: royal-blue - categories: - - categories + category: + - category tax-category: standard-taxable default-sku: default-sku ec-product-type: ff42fee0113744f693a764e3431a9cc2 skus: - - id: 580e63fc8c9a982ac9b8b745 + - id: 66072fb71b89448912e2681c cmsLocaleId: 653ad57de882f528b32e810e lastPublished: '2023-03-17T18:47:35Z' lastUpdated: '2023-03-17T18:47:35Z' createdOn: '2023-03-17T18:47:35Z' fieldData: sku-values: - ff42fee0113744f693a764e3431a9cc2: 64a74715c456e36762fc39a1 - name: Blue T-shirt - slug: t-shirt-blue + color: blue + size: small + name: Colorful T-shirt - Default + slug: colorful-t-shirt-default price: - value: 100 + value: 2499 unit: USD - quantity: 10 + currency: USD + main-image: https://www.example.com/image.jpg + sku: '1234567890' + sku-properties: + - id: Color + name: Color + enum: + - id: royal-blue + name: Royal Blue + slug: royal-blue update: path: /sites/{site_id}/products/{product_id} method: PATCH - auth: true + auth: + - OAuth2: + - ecommerce:write docs: > Update an existing Product. @@ -303,6 +384,7 @@ service: response: docs: Request was successful type: root.Product + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -334,18 +416,20 @@ service: - id: Color name: Color enum: - - id: id + - id: royal-blue name: Royal Blue slug: royal-blue - categories: - - categories + category: + - category tax-category: standard-taxable default-sku: default-sku ec-product-type: ff42fee0113744f693a764e3431a9cc2 create-sku: path: /sites/{site_id}/products/{product_id}/skus method: POST - auth: true + auth: + - OAuth2: + - ecommerce:write docs: > Create additional SKUs to manage every [option and variant of your Product.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants) @@ -366,7 +450,7 @@ service: product_id: type: string docs: Unique identifier for a Product - display-name: Create SKU + display-name: Create SKUs request: name: ProductsCreateSkuRequest body: @@ -379,6 +463,7 @@ service: response: docs: Request was successful type: ProductsCreateSkuResponse + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -393,28 +478,51 @@ service: product_id: 580e63fc8c9a982ac9b8b745 request: skus: - - {} + - id: 66072fb71b89448912e2681c + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35Z' + lastUpdated: '2023-03-17T18:47:35Z' + createdOn: '2023-03-17T18:47:35Z' + fieldData: + name: Colorful T-shirt - Default + slug: colorful-t-shirt-default + price: + value: 2499 + unit: USD + currency: USD response: body: skus: - - id: 580e63fc8c9a982ac9b8b745 + - id: 66072fb71b89448912e2681c cmsLocaleId: 653ad57de882f528b32e810e lastPublished: '2023-03-17T18:47:35Z' lastUpdated: '2023-03-17T18:47:35Z' createdOn: '2023-03-17T18:47:35Z' fieldData: sku-values: - ff42fee0113744f693a764e3431a9cc2: 64a74715c456e36762fc39a1 - name: Blue T-shirt - slug: t-shirt-blue + color: blue + size: small + name: Colorful T-shirt - Default + slug: colorful-t-shirt-default price: - value: 100 + value: 2499 unit: USD - quantity: 10 + currency: USD + main-image: https://www.example.com/image.jpg + sku: '1234567890' + sku-properties: + - id: Color + name: Color + enum: + - id: royal-blue + name: Royal Blue + slug: royal-blue update-sku: path: /sites/{site_id}/products/{product_id}/skus/{sku_id} method: PATCH - auth: true + auth: + - OAuth2: + - ecommerce:write docs: > Update a specified SKU. @@ -448,6 +556,7 @@ service: response: docs: Request was successful type: root.Sku + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -462,22 +571,36 @@ service: product_id: 580e63fc8c9a982ac9b8b745 sku_id: 5e8518516e147040726cc415 request: - sku: {} + sku: + id: 66072fb71b89448912e2681c + cmsLocaleId: 653ad57de882f528b32e810e + lastPublished: '2023-03-17T18:47:35Z' + lastUpdated: '2023-03-17T18:47:35Z' + createdOn: '2023-03-17T18:47:35Z' + fieldData: + name: Colorful T-shirt - Default + slug: colorful-t-shirt-default + price: + value: 2499 + unit: USD + currency: USD response: body: - id: 580e63fc8c9a982ac9b8b745 + id: 66072fb71b89448912e2681c cmsLocaleId: 653ad57de882f528b32e810e lastPublished: '2023-03-17T18:47:35Z' lastUpdated: '2023-03-17T18:47:35Z' createdOn: '2023-03-17T18:47:35Z' fieldData: sku-values: - ff42fee0113744f693a764e3431a9cc2: 64a74715c456e36762fc39a1 - name: Blue T-shirt - slug: t-shirt-blue + color: blue + size: small + name: Colorful T-shirt - Default + slug: colorful-t-shirt-default price: - value: 100 + value: 2499 unit: USD + currency: USD compare-at-price: value: 100 unit: USD @@ -488,13 +611,32 @@ service: trial: 7 plans: - {} - track-inventory: true - quantity: 10 + main-image: https://www.example.com/image.jpg + sku: '1234567890' + sku-properties: + - id: Color + name: Color + enum: + - id: royal-blue + name: Royal Blue + slug: royal-blue source: openapi: ../../../openapi/referenced-specs/v2.yml types: + ProductSkuCreateProduct: + properties: + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true + ProductSkuCreateSku: + properties: + fieldData: optional + source: + openapi: ../../../openapi/referenced-specs/v2.yml + inline: true ProductsCreateSkuResponse: properties: - skus: optional> + skus: list source: openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/scripts.yml b/.mock/definition/scripts.yml index 8236ed2..089d5f8 100644 --- a/.mock/definition/scripts.yml +++ b/.mock/definition/scripts.yml @@ -7,25 +7,17 @@ service: list: path: /sites/{site_id}/registered_scripts method: GET - auth: true + auth: + - OAuth2: + - custom_code:read docs: > - List of scripts registered to a Site. + Get a list of scripts that have been registered to a site. A site can + have a maximum of 800 registered scripts. - In order to use the Custom Code APIs for Sites and Pages, Custom Code - Scripts must first be registered - - to a Site via the `registered_scripts` endpoints, and then applied to a - Site or Page using the appropriate - - `custom_code` endpoints. - - Additionally, Scripts can be remotely hosted, or registered as inline - snippets. - - - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -39,6 +31,7 @@ service: response: docs: Request was successful type: root.RegisteredScriptList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -76,29 +69,22 @@ service: createdOn: '2022-10-26T00:28:54.191Z' lastUpdated: lastUpdated version: 1.0.0 + pagination: + limit: 100 + offset: 0 + total: 3 register-hosted: path: /sites/{site_id}/registered_scripts/hosted method: POST - auth: true - docs: > - Add a script to a Site's Custom Code registry. - - - In order to use the Custom Code APIs for Sites and Pages, Custom Code - Scripts must first be registered - - to a Site via the `registered_scripts` endpoints, and then applied to a - Site or Page using the appropriate - - `custom_code` endpoints. - - Additionally, Scripts can be remotely hosted, or registered as inline - snippets. - - - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + auth: + - OAuth2: + - custom_code:write + docs: | + Register a hosted script to a site. + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` source: @@ -138,6 +124,7 @@ service: response: docs: Request was successful type: root.CustomCodeHostedResponse + status-code: 201 errors: - root.BadRequestError - root.UnauthorizedError @@ -166,23 +153,17 @@ service: register-inline: path: /sites/{site_id}/registered_scripts/inline method: POST - auth: true + auth: + - OAuth2: + - custom_code:write docs: > - Add a script to a Site's Custom Code registry. Inline scripts can be - between 1 and 2000 characters. - + Register an inline script to a site. Inline scripts are limited to 2000 + characters. - In order to use the Custom Code APIs for Sites and Pages, Custom Code - Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a - Site or Page using the appropriate - - `custom_code` endpoints. - - - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -225,6 +206,7 @@ service: response: docs: Created type: root.CustomCodeInlineResponse + status-code: 201 errors: - root.BadRequestError - root.UnauthorizedError @@ -232,7 +214,8 @@ service: - root.TooManyRequestsError - root.InternalServerError examples: - - path-parameters: + - name: CustomCodeInlineResponse + path-parameters: site_id: 580e63e98c9a982ac9b8b741 request: sourceCode: alert('hello world'); diff --git a/.mock/definition/sites.yml b/.mock/definition/sites.yml index cea8997..ebc7cd0 100644 --- a/.mock/definition/sites.yml +++ b/.mock/definition/sites.yml @@ -7,9 +7,16 @@ service: create: path: /workspaces/{workspace_id}/sites method: POST - auth: true - docs: | - Create a site. This endpoint requires an Enterprise workspace. + auth: + - OAuth2: + - sites:write + docs: > + Create a site. + + + This endpoint requires an Enterprise + workspace. + Required scope | `workspace:write` source: @@ -36,6 +43,7 @@ service: response: docs: Request was successful type: root.Site + status-code: 201 errors: - root.BadRequestError - root.UnauthorizedError @@ -54,12 +62,12 @@ service: id: 670ecf86817e3cc7a510eb6a workspaceId: 625860a7a6c16d624927122f createdOn: '2024-10-15T20:24:38Z' - displayName: The Hitchiker‘s Guide + displayName: The Hitchiker's Guide shortName: hitchikers-guide lastPublished: '2016-10-24T19:43:17Z' lastUpdated: '2024-10-15T20:24:38Z' previewUrl: >- - https://d1otoma47x30pg.cloudfront.net/580e63e98c9a982ac9b8b741/201610241243.png + https://dev-assets.website-files.com/580e63e98c9a982ac9b8b741/201610241243.png timeZone: America/Los_Angeles parentFolderId: 670ece123598db72d9648be1 customDomains: @@ -84,12 +92,14 @@ service: redirect: true subdirectory: '' tag: en-US - dataCollectionEnabled: false + dataCollectionEnabled: true dataCollectionType: always list: path: /sites method: GET - auth: true + auth: + - OAuth2: + - sites:read docs: | List of all sites the provided access token is able to access. @@ -100,6 +110,7 @@ service: response: docs: Request was successful type: root.Sites + status-code: 200 errors: - root.UnauthorizedError - root.NotFoundError @@ -116,7 +127,7 @@ service: lastPublished: '2023-04-02T12:42:00Z' lastUpdated: '2016-10-24T19:43:17Z' previewUrl: >- - https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b741/197910121200.png + https://dev-assets.website-files.com/42e63e98c9a982ac9b8b741/197910121200.png timeZone: DeepSpace/InfiniteImprobability parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 customDomains: @@ -157,7 +168,7 @@ service: lastPublished: '2023-04-02T12:45:00Z' lastUpdated: '2016-10-24T19:43:17Z' previewUrl: >- - https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b742/198110121200.png + https://dev-assets.website-files.com/42e63e98c9a982ac9b8b742/198110121200.png timeZone: DeepSpace/Depression parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 customDomains: @@ -191,7 +202,7 @@ service: lastPublished: '2023-04-02T12:50:00Z' lastUpdated: '2016-10-24T19:43:17Z' previewUrl: >- - https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b743/198210121200.png + https://dev-assets.website-files.com/42e63e98c9a982ac9b8b743/198210121200.png timeZone: Vogsphere/PoetryHall parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 customDomains: @@ -220,7 +231,9 @@ service: get: path: /sites/{site_id} method: GET - auth: true + auth: + - OAuth2: + - sites:read docs: | Get details of a site. @@ -235,6 +248,7 @@ service: response: docs: Request was successful type: root.Site + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -242,7 +256,8 @@ service: - root.TooManyRequestsError - root.InternalServerError examples: - - path-parameters: + - name: SiteWithLocales + path-parameters: site_id: 580e63e98c9a982ac9b8b741 response: body: @@ -287,9 +302,16 @@ service: delete: path: /sites/{site_id} method: DELETE - auth: true - docs: | - Delete a site. This endpoint requires an Enterprise workspace. + auth: + - OAuth2: + - sites:write + docs: > + Delete a site. + + + This endpoint requires an Enterprise + workspace. + Required scope | `sites:write` source: @@ -312,9 +334,16 @@ service: update: path: /sites/{site_id} method: PATCH - auth: true - docs: | - Update a site. This endpoint requires an Enterprise workspace. + auth: + - OAuth2: + - sites:write + docs: > + Update a site. + + + This endpoint requires an Enterprise + workspace. + Required scope | `sites:write` source: @@ -338,6 +367,7 @@ service: response: docs: Request was successful type: root.Site + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -392,7 +422,9 @@ service: get-custom-domain: path: /sites/{site_id}/custom_domains method: GET - auth: true + auth: + - OAuth2: + - sites:read docs: | Get a list of all custom domains related to site. @@ -407,6 +439,7 @@ service: response: docs: Request was successful type: root.Domains + status-code: 200 errors: - root.UnauthorizedError - root.ForbiddenError @@ -428,13 +461,19 @@ service: publish: path: /sites/{site_id}/publish method: POST - auth: true + auth: + - OAuth2: + - sites:write docs: > - Publishes a site to one or more more domains. + Publishes a site to one or more more domains. + + To publish to a specific custom domain, use the domain IDs from the [Get + Custom Domains](/data/reference/sites/get-custom-domain) endpoint. - This endpoint has a limit of - one successful publish queue per minute. + + This endpoint has a + specific rate limit of one successful publish queue per minute. Required scope | `sites:write` @@ -460,6 +499,7 @@ service: response: docs: Request accepted type: SitesPublishResponse + status-code: 202 errors: - root.BadRequestError - root.UnauthorizedError @@ -467,9 +507,14 @@ service: - root.NotFoundError - root.TooManyRequestsError examples: - - path-parameters: + - name: DomainIDs + path-parameters: site_id: 580e63e98c9a982ac9b8b741 - request: {} + request: + customDomains: + - 660c6449dd97ebc7346ac629 + - 660c6449dd97ebc7346ac62f + publishToWebflowSubdomain: false response: body: customDomains: @@ -493,3 +538,21 @@ types: default: false source: openapi: ../../../openapi/referenced-specs/v2.yml +webhooks: + site_publish: + audiences: [] + method: POST + display-name: Site Publish + headers: {} + payload: root.SitePublish + examples: + - payload: + triggerType: site_publish + payload: + siteId: 62749158efef318abc8d5a0f + publishedOn: '2024-07-26T16:43:20Z' + domains: + - heartofgold.webflow.io + publishedBy: + displayName: Zaphod BeebleBrox + docs: Information about a site that was published diff --git a/.mock/definition/sites/activityLogs.yml b/.mock/definition/sites/activityLogs.yml index 1468f52..01f30f9 100644 --- a/.mock/definition/sites/activityLogs.yml +++ b/.mock/definition/sites/activityLogs.yml @@ -7,10 +7,18 @@ service: list: path: /sites/{site_id}/activity_logs method: GET - auth: true - docs: >- - Retrieve Activity Logs for a specific Site. Requires Site to be on an - Enterprise plan.

Required scope | `site_activity:read` + auth: + - OAuth2: + - site_activity:read + docs: > + Retrieve Activity Logs for a specific Site. + + + This endpoint requires an Enterprise + workspace. + + + Required scope: `site_activity:read` source: openapi: ../../../openapi/referenced-specs/v2.yml path-parameters: @@ -22,16 +30,17 @@ service: name: ActivityLogsListRequest query-parameters: limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records response: docs: A list of site activity logs type: root.SiteActivityLogResponse + status-code: 200 errors: - root.ForbiddenError - root.NotFoundError @@ -40,6 +49,9 @@ service: examples: - path-parameters: site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + limit: 1 + offset: 1 response: body: items: diff --git a/.mock/definition/sites/comments.yml b/.mock/definition/sites/comments.yml new file mode 100644 index 0000000..3885152 --- /dev/null +++ b/.mock/definition/sites/comments.yml @@ -0,0 +1,352 @@ +types: + CommentsListCommentThreadsRequestSortBy: + enum: + - createdOn + - lastUpdated + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentsListCommentThreadsRequestSortOrder: + enum: + - asc + - desc + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentsGetCommentThreadRequestSortBy: + enum: + - createdOn + - lastUpdated + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentsGetCommentThreadRequestSortOrder: + enum: + - asc + - desc + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentsListCommentRepliesRequestSortBy: + enum: + - createdOn + - lastUpdated + source: + openapi: ../../../openapi/referenced-specs/v2.yml + CommentsListCommentRepliesRequestSortOrder: + enum: + - asc + - desc + source: + openapi: ../../../openapi/referenced-specs/v2.yml +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + list-comment-threads: + path: /sites/{site_id}/comments + method: GET + auth: + - OAuth2: + - comments:read + docs: | + List all comment threads for a site. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Comment Threads + request: + name: CommentsListCommentThreadsRequest + query-parameters: + localeId: + type: optional + docs: > + Unique identifier for a specific Locale. + + + [Lear more about + localization.](/data/v2.0.0/docs/working-with-localization) + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + sortBy: + type: optional + docs: >- + Sort results by the provided value. Only allowed when sortOrder is + provided. + sortOrder: + type: optional + docs: Sorts the results by asc or desc + response: + docs: Request was successful + type: root.CommentThreadList + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + offset: 1 + limit: 1 + sortBy: createdOn + sortOrder: asc + response: + body: + comments: + - id: 679d2ddb5196117ad04d1ffa + siteId: 679826b3b20b045e176bc4b5 + pageId: 679826b3b20b045e176bc4bc + localeId: 67993753d910db250db64b3e + itemId: 580e64008c9a982ac9b8b754 + breakpoint: main + url: >- + https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc + content: 'Let''s go to the pub! [[6287ec36a841b25637c663df]] ' + isResolved: false + author: + userId: 6287ec36a841b25637c663df + email: ford.prefect@heartofgold.spaceship + name: Ford Prefect + mentionedUsers: + - userId: 6287ec36a841b25637c663df + email: arthur.dent@heartofgold.spaceship + name: Arthur Dent + createdOn: '2025-01-31T20:08:59.759Z' + lastUpdated: '2025-01-31T20:08:59.759Z' + - id: 679d2ddb5196117ad04d1ffc + siteId: 679826b3b20b045e176bc4b5 + pageId: 679826b3b20b045e176bc4bc + localeId: 67993753d910db250db64b3e + itemId: 580e64008c9a982ac9b8b754 + breakpoint: main + url: >- + https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc + content: >- + You have five minutes left to drink it + [[6287ec36a841b25637c663df]] + isResolved: false + author: + userId: 6287ec36a841b25637c663df + email: ford.prefect@heartofgold.spaceship + name: Ford Prefect + mentionedUsers: + - userId: 6287ec36a841b25637c663df + email: arthur.dent@heartofgold.spaceship + name: Arthur Dent + createdOn: '2025-01-31T20:08:59.759Z' + lastUpdated: '2025-01-31T20:08:59.759Z' + pagination: + limit: 2 + offset: 0 + total: 2 + get-comment-thread: + path: /sites/{site_id}/comments/{comment_thread_id} + method: GET + auth: + - OAuth2: + - comments:read + docs: | + Get details of a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + comment_thread_id: + type: string + docs: Unique identifier for a Comment Thread + display-name: Get Comment Thread + request: + name: CommentsGetCommentThreadRequest + query-parameters: + localeId: + type: optional + docs: > + Unique identifier for a specific Locale. + + + [Lear more about + localization.](/data/v2.0.0/docs/working-with-localization) + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + sortBy: + type: optional + docs: >- + Sort results by the provided value. Only allowed when sortOrder is + provided. + sortOrder: + type: optional + docs: Sorts the results by asc or desc + response: + docs: Request was successful + type: root.CommentThread + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + comment_thread_id: 580e63e98c9a982ac9b8b741 + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + offset: 1 + limit: 1 + sortBy: createdOn + sortOrder: asc + response: + body: + id: 580e64008c9a982ac9b8b754 + siteId: 580e64008c9a982ac9b8b754 + pageId: 580e64008c9a982ac9b8b754 + localeId: 580e64008c9a982ac9b8b754 + itemId: 580e64008c9a982ac9b8b754 + breakpoint: main + url: >- + https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc + content: This is a comment reply + isResolved: true + author: + userId: userId + email: email + name: name + mentionedUsers: + - userId: 6287ec36a841b25637c663df + email: arthur.dent@heartofgold.spaceship + name: Arthur Dent + createdOn: '2023-03-17T18:47:35.560Z' + lastUpdated: '2023-03-17T18:47:35.560Z' + list-comment-replies: + path: /sites/{site_id}/comments/{comment_thread_id}/replies + method: GET + auth: + - OAuth2: + - comments:read + docs: | + List all replies to a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + comment_thread_id: + type: string + docs: Unique identifier for a Comment Thread + display-name: List Comment Replies + request: + name: CommentsListCommentRepliesRequest + query-parameters: + localeId: + type: optional + docs: > + Unique identifier for a specific Locale. + + + [Lear more about + localization.](/data/v2.0.0/docs/working-with-localization) + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + sortBy: + type: optional + docs: >- + Sort results by the provided value. Only allowed when sortOrder is + provided. + sortOrder: + type: optional + docs: Sorts the results by asc or desc + response: + docs: Request was successful + type: root.CommentReplyList + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + comment_thread_id: 580e63e98c9a982ac9b8b741 + query-parameters: + localeId: 65427cf400e02b306eaa04a0 + offset: 1 + limit: 1 + sortBy: createdOn + sortOrder: asc + response: + body: + comments: + - id: 679d2ddb5196117ad04d1ffa + commentId: 679d2ddb5196117ad04d1ff8 + siteId: 679826b3b20b045e176bc4b5 + pageId: 679826b3b20b045e176bc4bc + localeId: 67993753d910db250db64b3e + breakpoint: main + content: >- + This comment mentions another user + [[6287ec36a841b25637c663df]] + isResolved: false + author: + id: id + email: email + name: name + mentionedUsers: + - id: id + email: arthur.dent@example.com + name: Arthur Dent + lastUpdated: '2025-01-31T20:08:59.759Z' + createdOn: '2025-01-31T20:08:59.759Z' + pagination: + limit: 2 + offset: 0 + total: 1 + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/forms.yml b/.mock/definition/sites/forms.yml new file mode 100644 index 0000000..27e1e1d --- /dev/null +++ b/.mock/definition/sites/forms.yml @@ -0,0 +1,316 @@ +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + list-submissions-by-site: + path: /sites/{site_id}/form_submissions + method: GET + auth: + - OAuth2: + - forms:read + docs: > + List all form submissions for a given site with the ability to filter + submissions by a centralized `elementId`. + + + Add `elementId` when you want to filter form submissions to a specific + form in a site. You can get the `elementId` from the [List forms + endpoint](/data/reference/forms/forms/list) (displayed as + `formElementId` in the response). + + + + + When a form is used in a Webflow component definition, each instance of + the component will yield a unique form. Adding the `elementId` in this + request ensures this API response includes all submissions from that + core form, wherever that form is used in instantiated components. + + + + + Use the [List Form Submissions + endpoint](/data/reference/forms/form-submissions/list-submissions) to + list form submissions for a given form ID. + + + Required scope | `forms:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: List Form Submissions by Site + request: + name: FormsListSubmissionsBySiteRequest + query-parameters: + elementId: + type: optional + docs: Identifier for an element + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + response: + docs: Request was successful + type: root.FormSubmissionList + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + elementId: 18259716-3e5a-646a-5f41-5dc4b9405aa0 + offset: 1 + limit: 1 + response: + body: + formSubmissions: + - id: 6321ca84df3949bfc6752327 + displayName: Sample Form + siteId: 62749158efef318abc8d5a0f + workspaceId: 62749158efef318abc8d5a0f + dateSubmitted: '2022-09-14T12:35:16Z' + formResponse: + First Name: Arthur + Last Name: Dent + - id: 660d64fabf6e0a0d4edab981 + displayName: Sample Form + siteId: 62749158efef318abc8d5a0f + workspaceId: 62749158efef318abc8d5a0f + dateSubmitted: '2022-09-14T12:35:16Z' + formResponse: + First Name: Ford + Last Name: Prefect + pagination: + limit: 25 + offset: 0 + total: 2 + list-submissions: + path: /sites/{site_id}/forms/{form_id}/submissions + method: GET + auth: + - OAuth2: + - forms:read + docs: > + List form submissions for a given form ID within a specific site. + + + Use the [List Form Submissions by Site + endpoint](/data/reference/forms/form-submissions/list-submissions-by-site) + to list form submissions for a given site with the ability to filter by + a `formElementId`. + + + Required scope | `forms:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + form_id: + type: string + docs: Unique identifier for a Form + display-name: List Form Submissions + request: + name: FormsListSubmissionsRequest + query-parameters: + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + response: + docs: Request was successful + type: root.FormSubmissionList + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + form_id: 580e63e98c9a982ac9b8b741 + query-parameters: + offset: 1 + limit: 1 + response: + body: + formSubmissions: + - id: 6321ca84df3949bfc6752327 + displayName: Sample Form + siteId: 62749158efef318abc8d5a0f + workspaceId: 62749158efef318abc8d5a0f + dateSubmitted: '2022-09-14T12:35:16Z' + formResponse: + First Name: Arthur + Last Name: Dent + - id: 660d64fabf6e0a0d4edab981 + displayName: Sample Form + siteId: 62749158efef318abc8d5a0f + workspaceId: 62749158efef318abc8d5a0f + dateSubmitted: '2022-09-14T12:35:16Z' + formResponse: + First Name: Ford + Last Name: Prefect + pagination: + limit: 25 + offset: 0 + total: 2 + get-submission: + path: /sites/{site_id}/form_submissions/{form_submission_id} + method: GET + auth: + - OAuth2: + - forms:read + docs: | + Get information about a form submission within a specific site. + + Required scope | `forms:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + form_submission_id: + type: string + docs: Unique identifier for a Form Submission + display-name: Get Form Submission by Site + response: + docs: Request was successful + type: root.FormSubmission + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + form_submission_id: 580e63e98c9a982ac9b8b741 + response: + body: + id: 6321ca84df3949bfc6752327 + displayName: Sample Form + siteId: 62749158efef318abc8d5a0f + workspaceId: 62749158efef318abc8d5a0f + dateSubmitted: '2022-09-14T12:35:16Z' + formResponse: + First Name: Arthur + Last Name: Dent + delete-submission: + path: /sites/{site_id}/form_submissions/{form_submission_id} + method: DELETE + auth: + - OAuth2: + - forms:write + docs: | + Delete a form submission within a specific site. + + Required scope | `forms:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + form_submission_id: + type: string + docs: Unique identifier for a Form Submission + display-name: Delete Form Submission by Site + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + form_submission_id: 580e63e98c9a982ac9b8b741 + update-submission: + path: /sites/{site_id}/form_submissions/{form_submission_id} + method: PATCH + auth: + - OAuth2: + - forms:write + docs: | + Update hidden fields on a form submission within a specific site. + + Required scope | `forms:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + form_submission_id: + type: string + docs: Unique identifier for a Form Submission + display-name: Modify Form Submission by Site + request: + name: FormsUpdateSubmissionRequest + body: + properties: + formSubmissionData: + type: optional> + docs: >- + An existing **hidden field** defined on the form schema, and the + corresponding value to set + content-type: application/json + response: + docs: Request was successful + type: root.FormSubmission + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.ConflictError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + form_submission_id: 580e63e98c9a982ac9b8b741 + request: {} + response: + body: + id: 6321ca84df3949bfc6752327 + displayName: Sample Form + siteId: 62749158efef318abc8d5a0f + workspaceId: 62749158efef318abc8d5a0f + dateSubmitted: '2022-09-14T12:35:16Z' + formResponse: + First Name: Arthur + Last Name: Dent + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/plans.yml b/.mock/definition/sites/plans.yml index ae9de6d..4f662bc 100644 --- a/.mock/definition/sites/plans.yml +++ b/.mock/definition/sites/plans.yml @@ -7,10 +7,17 @@ service: get-site-plan: path: /sites/{site_id}/plan method: GET - auth: true - docs: | + auth: + - OAuth2: + - sites:read + docs: > Get site plan details for the specified Site. + + This endpoint requires an Enterprise + workspace. + + Required scope | `sites:read` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -22,6 +29,7 @@ service: response: docs: Request was successful type: root.SitePlan + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError diff --git a/.mock/definition/sites/redirects.yml b/.mock/definition/sites/redirects.yml index b104d86..806117c 100644 --- a/.mock/definition/sites/redirects.yml +++ b/.mock/definition/sites/redirects.yml @@ -7,15 +7,20 @@ service: list: path: /sites/{site_id}/redirects method: GET - auth: true + auth: + - OAuth2: + - sites:read docs: > - Fetch a list of all URL redirect rules configured for a specific site. + Fetch a list of all 301 redirect rules configured for a specific site. Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + This endpoint requires an Enterprise + workspace. + Required scope: `sites:read` source: @@ -24,10 +29,11 @@ service: site_id: type: string docs: Unique identifier for a Site - display-name: Get URL redirects + display-name: Get 301 redirects response: docs: Request was successful type: root.Redirects + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -53,9 +59,11 @@ service: create: path: /sites/{site_id}/redirects method: POST - auth: true + auth: + - OAuth2: + - sites:write docs: > - Add a new URL redirection rule to a site. + Add a new 301 redirection rule to a site. This endpoint allows you to define a source path (`fromUrl`) and its @@ -64,6 +72,10 @@ service: restructuring URLs, or handling outdated links. + This endpoint requires an Enterprise + workspace. + + Required scope: `sites:write` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -71,13 +83,14 @@ service: site_id: type: string docs: Unique identifier for a Site - display-name: Create a URL redirect + display-name: Create a 301 redirect request: body: root.Redirect content-type: application/json response: docs: Request was successful type: root.Redirect + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -99,14 +112,22 @@ service: delete: path: /sites/{site_id}/redirects/{redirect_id} method: DELETE - auth: true + auth: + - OAuth2: + - sites:write docs: > - Remove a URL redirection rule from a site. + Remove a 301 redirection rule from a site. + This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + + This endpoint requires an Enterprise + workspace. + + Required scope: `sites:write` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -117,10 +138,11 @@ service: redirect_id: type: string docs: Unique identifier site rediect - display-name: Delete URL redirects + display-name: Delete 301 redirects response: docs: Request was successful type: root.Redirects + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -147,9 +169,17 @@ service: update: path: /sites/{site_id}/redirects/{redirect_id} method: PATCH - auth: true - docs: | - Update a URL redirection rule from a site. + auth: + - OAuth2: + - sites:write + docs: > + Update a 301 redirection rule from a site. + + + This endpoint requires an Enterprise + workspace. + + Required scope: `sites:write` source: openapi: ../../../openapi/referenced-specs/v2.yml @@ -160,13 +190,14 @@ service: redirect_id: type: string docs: Unique identifier site rediect - display-name: Update URL redirect + display-name: Update 301 redirect request: body: root.Redirect content-type: application/json response: docs: Request was successful type: root.Redirect + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError diff --git a/.mock/definition/sites/robotsTxt.yml b/.mock/definition/sites/robotsTxt.yml new file mode 100644 index 0000000..1aaf6cf --- /dev/null +++ b/.mock/definition/sites/robotsTxt.yml @@ -0,0 +1,229 @@ +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + get: + path: /sites/{site_id}/robots_txt + method: GET + auth: + - OAuth2: + - site_config:read + docs: > + Retrieve the robots.txt configuration for various user agents. + + + This endpoint requires an Enterprise + workspace. + + + Required scope: `site_config:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Get robots.txt + response: + docs: Request was successful + type: root.Robots + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + response: + body: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + put: + path: /sites/{site_id}/robots_txt + method: PUT + auth: + - OAuth2: + - site_config:write + docs: > + Replace the `robots.txt` configuration for various user agents. + + + This endpoint requires an Enterprise + workspace. + + + Required scope | `site_config:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Replace robots.txt + request: + body: root.Robots + content-type: application/json + response: + docs: Request was successful + type: root.Robots + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + response: + body: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + delete: + path: /sites/{site_id}/robots_txt + method: DELETE + auth: + - OAuth2: + - site_config:write + docs: > + Remove specific rules for a user-agent in your `robots.txt` file. To + delete all rules for a user-agent, provide an empty rule set. This will + remove the user-agent's entry entirely, leaving it subject to your + site's default crawling behavior. + + + **Note:** Deleting a user-agent with no rules will make the user-agent's + access unrestricted unless other directives apply. + + + This endpoint requires an Enterprise + workspace. + + + Required scope: `site_config:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Delete robots.txt + request: + body: root.Robots + content-type: application/json + response: + docs: Request was successful + type: root.Robots + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + rules: + - userAgent: '*' + allows: + - /public + disallows: + - /bubbles + response: + body: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + patch: + path: /sites/{site_id}/robots_txt + method: PATCH + auth: + - OAuth2: + - site_config:write + docs: > + Update the `robots.txt` configuration for various user agents. + + + This endpoint requires an Enterprise + workspace. + + + Required scope | `site_config:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Update robots.txt + request: + body: root.Robots + content-type: application/json + response: + docs: Request was successful + type: root.Robots + status-code: 200 + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + response: + body: + rules: + - userAgent: googlebot + allows: + - /public + disallows: + - /vogon-poetry + - /total-perspective-vortex + sitemap: https://heartofgold.ship/sitemap.xml + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/scripts.yml b/.mock/definition/sites/scripts.yml index 92ad0e4..6762c85 100644 --- a/.mock/definition/sites/scripts.yml +++ b/.mock/definition/sites/scripts.yml @@ -7,14 +7,15 @@ service: get-custom-code: path: /sites/{site_id}/custom_code method: GET - auth: true - docs: > - Get all registered scripts that have been applied to a specific Site. - - - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + auth: + - OAuth2: + - custom_code:read + docs: | + Get all scripts applied to a site by the App. + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` source: @@ -27,6 +28,7 @@ service: response: docs: Request was successful type: root.ScriptApplyList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -54,22 +56,20 @@ service: upsert-custom-code: path: /sites/{site_id}/custom_code method: PUT - auth: true + auth: + - OAuth2: + - custom_code:write docs: > - Add a registered script to a Site. - - - In order to use the Custom Code APIs for Sites and Pages, Custom Code - Scripts must first be registered + Apply registered scripts to a site. If you have multiple scripts your + App needs to apply or maintain on a site, ensure they are always + included in the request body for this endpoint. To remove individual + scripts, simply call this endpoint without the script in the request + body. - to a Site via the `registered_scripts` endpoints, and then applied to a - Site or Page using the appropriate - `custom_code` endpoints. - - - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -86,6 +86,7 @@ service: response: docs: Request was successful type: root.ScriptApplyList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -123,13 +124,22 @@ service: delete-custom-code: path: /sites/{site_id}/custom_code method: DELETE - auth: true + auth: + - OAuth2: + - custom_code:write docs: > - Delete the custom code block that an app created for a Site + Remove all scripts from a site applied by the App. This endpoint will + not remove scripts from the site's registered scripts. + + + To remove individual scripts applied by the App, use the [Add/Update + Custom + Code](/data/reference/custom-code/custom-code-sites/upsert-custom-code) + endpoint. - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + Access to this endpoint requires a bearer token obtained from an + [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write` @@ -152,13 +162,19 @@ service: list-custom-code-blocks: path: /sites/{site_id}/custom_code/blocks method: GET - auth: true + auth: + - OAuth2: + - custom_code:read docs: > - Get all instances of Custom Code applied to a Site or Pages. + Get a list of scripts that have been applied to a site and/or individual + pages. - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. + + See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -173,16 +189,17 @@ service: name: ScriptsListCustomCodeBlocksRequest query-parameters: offset: - type: optional + type: optional docs: >- Offset used for pagination if the results have more than limit records limit: - type: optional + type: optional docs: 'Maximum number of records to be returned (max limit: 100)' response: docs: Request was successful type: root.ListCustomCodeBlocks + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -192,6 +209,9 @@ service: examples: - path-parameters: site_id: 580e63e98c9a982ac9b8b741 + query-parameters: + offset: 1 + limit: 1 response: body: blocks: diff --git a/.mock/definition/sites/wellKnown.yml b/.mock/definition/sites/wellKnown.yml new file mode 100644 index 0000000..10ef3e0 --- /dev/null +++ b/.mock/definition/sites/wellKnown.yml @@ -0,0 +1,130 @@ +types: + WellKnownFileContentType: + enum: + - value: application/json + name: ApplicationJson + - value: text/plain + name: TextPlain + docs: The content type of the file. Defaults to application/json + default: application/json + inline: true + source: + openapi: ../../../openapi/referenced-specs/v2.yml +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + put: + path: /sites/{site_id}/well_known + method: PUT + auth: + - OAuth2: + - site_config:write + docs: > + Upload a supported well-known file to a site. + + + The current restrictions on well-known files are as follows: + - Each file must be smaller than 100kb + - Less than 30 total files + - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` + + + `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. + + + This endpoint requires an Enterprise + workspace. + + + Required scope: `site_config:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Set a well-known file + request: + name: WellKnownFile + body: + properties: + fileName: + type: string + docs: The name of the file + fileData: + type: string + docs: The contents of the file + contentType: + type: optional + docs: The content type of the file. Defaults to application/json + default: application/json + content-type: application/json + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: + fileName: apple-app-site-association.txt + fileData: | + { + "applinks": { + "apps": [], + "details": [ + { + "appID": "ABCDE12345.com.example.app", + "paths": [ "/*", "/some/path/*" ] + } + ] + } + } + contentType: application/json + delete: + path: /sites/{site_id}/well_known + method: DELETE + auth: + - OAuth2: + - site_config:write + docs: > + Delete existing well-known files from a site. + + + This endpoint requires an Enterprise + workspace. + + + Required scope: `site_config:write` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + site_id: + type: string + docs: Unique identifier for a Site + display-name: Delete a well-known file + request: + name: WellKnownDeleteRequest + body: + properties: + fileNames: + type: optional> + docs: A list of file names to delete + content-type: application/json + errors: + - root.BadRequestError + - root.UnauthorizedError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + site_id: 580e63e98c9a982ac9b8b741 + request: {} + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/token.yml b/.mock/definition/token.yml index 033c5c3..4b0e365 100644 --- a/.mock/definition/token.yml +++ b/.mock/definition/token.yml @@ -7,7 +7,9 @@ service: authorized-by: path: /token/authorized_by method: GET - auth: true + auth: + - OAuth2: + - authorized_user:read docs: | Information about the Authorized User @@ -18,6 +20,7 @@ service: response: docs: Request was successful type: root.AuthorizedUser + status-code: 200 errors: - root.UnauthorizedError - root.ForbiddenError @@ -31,7 +34,6 @@ service: introspect: path: /token/introspect method: GET - auth: true docs: > Information about the authorization token @@ -44,6 +46,7 @@ service: response: docs: Request was successful type: root.Authorization + status-code: 200 errors: - root.UnauthorizedError examples: diff --git a/.mock/definition/users.yml b/.mock/definition/users.yml deleted file mode 100644 index 19a17cc..0000000 --- a/.mock/definition/users.yml +++ /dev/null @@ -1,392 +0,0 @@ -types: - UsersListRequestSort: - enum: - - value: CreatedOn - name: CreatedOnAscending - docs: Sorts users in ascending order based on their created date - - value: '-CreatedOn' - name: CreatedOnDescending - docs: Sorts users in descending order based on their created date - - value: Email - name: EmailAscending - docs: Sorts users in ascending order based on their email - - value: '-Email' - name: EmailDescending - docs: Sorts users in descending order based on their email - - value: Status - name: StatusAscending - docs: Sorts users in ascending order based on their status - - value: '-Status' - name: StatusDescending - docs: Sorts users in descending order based on their status - - value: LastLogin - name: LastLoginAscending - docs: Sorts users in ascending order based on their last login date - - value: '-LastLogin' - name: LastLoginDescending - docs: Sorts users in descending order based on their last login date - - value: UpdatedOn - name: UpdatedOnAscending - docs: Sorts users in ascending order based on their update date - - value: '-UpdatedOn' - name: UpdatedOnDescending - docs: Sorts users in descending order based on their update date - source: - openapi: ../../../openapi/referenced-specs/v2.yml - UsersUpdateRequestData: - properties: - name: - type: optional - docs: | - The name of the user - accept-privacy: - type: optional - docs: | - Boolean indicating if the user has accepted the privacy policy - accept-communications: - type: optional - docs: | - Boolean indicating if the user has accepted to receive communications - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/users - method: GET - auth: true - docs: | - Get a list of users for a site - - Required scope | `users:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Users - request: - name: UsersListRequest - query-parameters: - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - sort: - type: optional - docs: | - Sort string to use when ordering users - - Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). - - Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) - response: - docs: Request was successful - type: root.UserList - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - count: 5 - limit: 5 - offset: 0 - total: 201 - users: - - id: 6287ec36a841b25637c663df - isEmailVerified: false - lastUpdated: '2022-05-20T13:46:12Z' - invitedOn: '2016-10-24T19:41:29Z' - createdOn: '2022-05-20T13:46:12Z' - lastLogin: '2016-10-24T19:41:29Z' - status: unverified - accessGroups: - - slug: vogon-construction-crew - type: admin - - id: 6287ec36a841b25637c663f0 - isEmailVerified: false - lastUpdated: '2022-05-19T05:32:04Z' - invitedOn: '2016-10-24T19:41:29Z' - createdOn: '2022-05-19T05:32:04Z' - lastLogin: '2016-10-24T19:41:29Z' - status: unverified - accessGroups: - - slug: improbability-drive-test-subjects - type: admin - - id: 6287ec36a841b25637c663d9 - isEmailVerified: true - lastUpdated: '2022-05-17T03:34:06Z' - invitedOn: '2016-10-24T19:41:29Z' - createdOn: '2022-05-17T03:34:06Z' - lastLogin: '2016-10-24T19:41:29Z' - status: verified - accessGroups: - - slug: heart-of-gold-crew - type: admin - - id: 6287ec37a841b25637c6641b - isEmailVerified: false - lastUpdated: '2022-05-15T03:46:09Z' - invitedOn: '2016-10-24T19:41:29Z' - createdOn: '2022-05-15T03:46:09Z' - lastLogin: '2016-10-24T19:41:29Z' - status: unverified - accessGroups: - - slug: hitchhikers-guide-research-team - type: admin - - id: 6287ec37a841b25637c66449 - isEmailVerified: true - lastUpdated: '2022-05-15T02:55:38Z' - invitedOn: '2016-10-24T19:41:29Z' - createdOn: '2022-05-15T02:55:38Z' - lastLogin: '2016-10-24T19:41:29Z' - status: verified - accessGroups: - - slug: milliways-reservationists - type: admin - get: - path: /sites/{site_id}/users/{user_id} - method: GET - auth: true - docs: | - Get a User by ID - - Required scope | `users:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - user_id: - type: string - docs: Unique identifier for a User - display-name: Get User - response: - docs: Request was successful - type: root.User - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - user_id: 580e63e98c9a982ac9b8b741 - response: - body: - id: 6287ec36a841b25637c663df - isEmailVerified: true - lastUpdated: '2022-05-20T13:46:12Z' - invitedOn: '2022-05-20T13:46:12Z' - createdOn: '2022-05-20T13:46:12Z' - lastLogin: '2022-05-20T13:46:12Z' - status: verified - accessGroups: - - slug: webflowers - type: admin - data: - data: - name: name - email: email - accept-privacy: true - accept-communications: true - additionalProperties: additionalProperties - delete: - path: /sites/{site_id}/users/{user_id} - method: DELETE - auth: true - docs: | - Delete a User by ID - - Required scope | `users:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - user_id: - type: string - docs: Unique identifier for a User - display-name: Delete User - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - user_id: 580e63e98c9a982ac9b8b741 - update: - path: /sites/{site_id}/users/{user_id} - method: PATCH - auth: true - docs: | - Update a User by ID - - Required scope | `users:write` - - The email and password - fields cannot be updated using this endpoint - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - user_id: - type: string - docs: Unique identifier for a User - display-name: Update User - request: - name: UsersUpdateRequest - body: - properties: - data: optional - accessGroups: - type: optional> - docs: > - An array of access group slugs. Access groups are assigned to - the user as type `admin` and the user remains in the group until - removed. - content-type: application/json - response: - docs: Request was successful - type: root.User - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - user_id: 580e63e98c9a982ac9b8b741 - request: - data: - name: Some One - accept-privacy: false - accept-communications: false - accessGroups: - - webflowers - - platinum - - free-tier - response: - body: - id: 6287ec36a841b25637c663df - isEmailVerified: true - lastUpdated: '2022-05-20T13:46:12Z' - invitedOn: '2022-05-20T13:46:12Z' - createdOn: '2022-05-20T13:46:12Z' - lastLogin: '2022-05-20T13:46:12Z' - status: verified - accessGroups: - - slug: webflowers - type: admin - data: - data: - name: name - email: email - accept-privacy: true - accept-communications: true - additionalProperties: additionalProperties - invite: - path: /sites/{site_id}/users/invite - method: POST - auth: true - docs: > - Create and invite a user with an email address. - - - The user will be sent and invite via email, which they will need to - accept in order to join paid any paid access group. - - - Required scope | `users:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Create and Invite a User - request: - name: UsersInviteRequest - body: - properties: - email: - type: string - docs: Email address of user to send invite to - validation: - format: email - accessGroups: - type: optional> - docs: > - An array of access group slugs. Access groups are assigned to - the user as type `admin` and the user remains in the group until - removed. - content-type: application/json - response: - docs: Request was successful - type: root.User - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - email: some.one@home.com - accessGroups: - - webflowers - response: - body: - id: 6287ec36a841b25637c663df - isEmailVerified: true - lastUpdated: '2022-05-20T13:46:12Z' - invitedOn: '2022-05-20T13:46:12Z' - createdOn: '2022-05-20T13:46:12Z' - lastLogin: '2022-05-20T13:46:12Z' - status: verified - accessGroups: - - slug: webflowers - type: admin - data: - data: - name: name - email: email - accept-privacy: true - accept-communications: true - additionalProperties: additionalProperties - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/webhooks.yml b/.mock/definition/webhooks.yml index d40e3e4..46bbb02 100644 --- a/.mock/definition/webhooks.yml +++ b/.mock/definition/webhooks.yml @@ -7,7 +7,6 @@ service: list: path: /sites/{site_id}/webhooks method: GET - auth: true docs: | List all App-created Webhooks registered for a given site @@ -22,6 +21,7 @@ service: response: docs: Request was successful type: root.WebhookList + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -33,10 +33,6 @@ service: site_id: 580e63e98c9a982ac9b8b741 response: body: - pagination: - limit: 100 - offset: 0 - total: 100 webhooks: - id: 57ca0a9e418c504a6e1acbb6 triggerType: form_submission @@ -65,10 +61,13 @@ service: name: Email Form lastTriggered: '2023-02-08T23:59:28Z' createdOn: '2016-07-19T01:43:40Z' + pagination: + limit: 100 + offset: 0 + total: 100 create: path: /sites/{site_id}/webhooks method: POST - auth: true docs: > Create a new Webhook. @@ -93,6 +92,7 @@ service: response: docs: Request was successful type: root.Webhook + status-code: 201 errors: - root.BadRequestError - root.UnauthorizedError @@ -124,7 +124,6 @@ service: get: path: /webhooks/{webhook_id} method: GET - auth: true docs: | Get a specific Webhook instance @@ -139,6 +138,7 @@ service: response: docs: Request was successful type: root.Webhook + status-code: 200 errors: - root.BadRequestError - root.UnauthorizedError @@ -162,7 +162,6 @@ service: delete: path: /webhooks/{webhook_id} method: DELETE - auth: true docs: | Remove a Webhook diff --git a/.mock/definition/workspaces/auditLogs.yml b/.mock/definition/workspaces/auditLogs.yml new file mode 100644 index 0000000..57b604a --- /dev/null +++ b/.mock/definition/workspaces/auditLogs.yml @@ -0,0 +1,126 @@ +types: + AuditLogsGetWorkspaceAuditLogsRequestSortOrder: + enum: + - asc + - desc + source: + openapi: ../../../openapi/referenced-specs/v2.yml + AuditLogsGetWorkspaceAuditLogsRequestEventType: + enum: + - user_access + - custom_role + - workspace_membership + - site_membership + - workspace_invitation + - workspace_setting + source: + openapi: ../../../openapi/referenced-specs/v2.yml +imports: + root: ../__package__.yml +service: + auth: false + base-path: '' + endpoints: + get-workspace-audit_logs: + path: /workspaces/{workspace_id_or_slug}/audit_logs + method: GET + auth: + - OAuth2: + - workspace_activity:read + docs: > + Get audit logs for a workspace. + + + This endpoint + requires an Enterprise workspace and a workspace token with the + `workspace_activity:read` scope. Create a workspace token from your + workspace dashboard integrations page to use this endpoint. + + + Required scope | `workspace_activity:read` + source: + openapi: ../../../openapi/referenced-specs/v2.yml + path-parameters: + workspace_id_or_slug: + type: string + docs: Unique identifier or slug for a Workspace + display-name: Get Workspace Audit Logs + request: + name: AuditLogsGetWorkspaceAuditLogsRequest + query-parameters: + limit: + type: optional + docs: 'Maximum number of records to be returned (max limit: 100)' + offset: + type: optional + docs: >- + Offset used for pagination if the results have more than limit + records + sortOrder: + type: optional + docs: Sorts the results by asc or desc + eventType: + type: optional + docs: The event type to filter by + from: + type: optional + docs: The start date to filter by + to: + type: optional + docs: The end date to filter by + response: + docs: A list of workspace audit logs + type: root.WorkspaceAuditLogResponse + status-code: 200 + errors: + - root.UnauthorizedError + - root.ForbiddenError + - root.NotFoundError + - root.TooManyRequestsError + - root.InternalServerError + examples: + - path-parameters: + workspace_id_or_slug: hitchhikers-workspace + query-parameters: + limit: 1 + offset: 1 + sortOrder: asc + eventType: user_access + from: '2025-06-22T16:00:31Z' + to: '2025-07-22T16:00:31Z' + response: + body: + items: + - eventSubType: login + eventType: user_access + timestamp: '2025-04-29T20:30:06Z' + actor: + id: 6661ccb359b561c69f29d554 + email: someone@email.com + workspace: + id: 6621ccb459b561c69f29d57c + slug: hitchhikers-workspace + - eventSubType: user_added + eventType: workspace_membership + timestamp: '2025-04-30T20:30:06Z' + actor: + id: 60492e55bbddce079561cd7a + email: someone@webflow.com + workspace: + id: 6621ccb459b561c69f29d57c + slug: hitchhikers-workspace + - eventSubType: user_added + eventType: site_membership + timestamp: '2025-04-30T00:33:31Z' + actor: + id: 671fe00d185fc8c1ad409d37 + email: someone@webflow.com + workspace: + id: 6621ccb459b561c69f29d57c + slug: hitchhikers-workspace + pagination: + limit: 10 + offset: 0 + total: 3 + source: + openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/fern.config.json b/.mock/fern.config.json index 8b3316e..9c2f634 100644 --- a/.mock/fern.config.json +++ b/.mock/fern.config.json @@ -1,4 +1,4 @@ { "organization" : "webflow", - "version" : "0.46.19" + "version" : "0.110.1" } \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 658601b..ea2269c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "annotated-types" @@ -38,13 +38,13 @@ trio = ["trio (>=0.26.1)"] [[package]] name = "certifi" -version = "2024.12.14" +version = "2026.2.25" description = "Python package for providing Mozilla's CA Bundle." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, - {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, + {file = "certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa"}, + {file = "certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7"}, ] [[package]] @@ -60,15 +60,18 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.2.2" +version = "1.3.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, - {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, + {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, + {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + [package.extras] test = ["pytest (>=6)"] @@ -130,13 +133,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "idna" -version = "3.10" +version = "3.11" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, + {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, + {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, ] [package.extras] @@ -144,13 +147,13 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 [[package]] name = "iniconfig" -version = "2.0.0" +version = "2.1.0" description = "brain-dead simple config-ini parsing" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, ] [[package]] @@ -201,24 +204,24 @@ reports = ["lxml"] [[package]] name = "mypy-extensions" -version = "1.0.0" +version = "1.1.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, + {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, + {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, ] [[package]] name = "packaging" -version = "24.2" +version = "26.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, - {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, + {file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"}, + {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}, ] [[package]] @@ -238,13 +241,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pydantic" -version = "2.10.5" +version = "2.10.6" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"}, - {file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"}, + {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, + {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, ] [package.dependencies] @@ -473,43 +476,58 @@ files = [ [[package]] name = "tomli" -version = "2.2.1" +version = "2.4.0" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" files = [ - {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, - {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, - {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, - {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, - {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, - {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, - {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, - {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, - {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, - {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, - {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, - {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, - {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, - {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, - {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, - {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, - {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, - {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, + {file = "tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867"}, + {file = "tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9"}, + {file = "tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95"}, + {file = "tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76"}, + {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d"}, + {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576"}, + {file = "tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a"}, + {file = "tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa"}, + {file = "tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614"}, + {file = "tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1"}, + {file = "tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8"}, + {file = "tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a"}, + {file = "tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1"}, + {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b"}, + {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51"}, + {file = "tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729"}, + {file = "tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da"}, + {file = "tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3"}, + {file = "tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0"}, + {file = "tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e"}, + {file = "tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4"}, + {file = "tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e"}, + {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c"}, + {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f"}, + {file = "tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86"}, + {file = "tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87"}, + {file = "tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132"}, + {file = "tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6"}, + {file = "tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc"}, + {file = "tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66"}, + {file = "tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d"}, + {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702"}, + {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8"}, + {file = "tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776"}, + {file = "tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475"}, + {file = "tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2"}, + {file = "tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9"}, + {file = "tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0"}, + {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df"}, + {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d"}, + {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f"}, + {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b"}, + {file = "tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087"}, + {file = "tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd"}, + {file = "tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4"}, + {file = "tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a"}, + {file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"}, ] [[package]] @@ -525,16 +543,16 @@ files = [ [[package]] name = "typing-extensions" -version = "4.12.2" +version = "4.13.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, + {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, + {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, ] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "2974ad2d485417c468bff08c2d5526b20e5e4790deaffc5363b3c831bebca3b3" +content-hash = "6f6c191c1028d17a97fdfa84cedfd3cef94b5d63d98b8c1d333b3398eeea9055" diff --git a/pyproject.toml b/pyproject.toml index 58c9529..66a8846 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "webflow" -version = "2.0.0b2" +version = "1.2.1" description = "" readme = "README.md" authors = [] @@ -33,7 +33,6 @@ Repository = 'https://github.com/webflow/webflow-python' [tool.poetry.dependencies] python = "^3.8" httpx = ">=0.21.2" -httpcore = "1.0.9" pydantic = ">= 1.9.2" pydantic-core = "^2.18.2" typing_extensions = ">= 4.0.0" diff --git a/reference.md b/reference.md index 5001bba..9abecdf 100644 --- a/reference.md +++ b/reference.md @@ -137,7 +137,9 @@ client.token.introspect()
-Create a site. This endpoint requires an Enterprise workspace. +Create a site. + +This endpoint requires an Enterprise workspace. Required scope | `workspace:write`
@@ -368,7 +370,9 @@ client.sites.get(
-Delete a site. This endpoint requires an Enterprise workspace. +Delete a site. + +This endpoint requires an Enterprise workspace. Required scope | `sites:write`
@@ -440,7 +444,9 @@ client.sites.delete(
-Update a site. This endpoint requires an Enterprise workspace. +Update a site. + +This endpoint requires an Enterprise workspace. Required scope | `sites:write`
@@ -600,9 +606,11 @@ client.sites.get_custom_domain(
-Publishes a site to one or more more domains. +Publishes a site to one or more more domains. + +To publish to a specific custom domain, use the domain IDs from the [Get Custom Domains](/data/reference/sites/get-custom-domain) endpoint. -This endpoint has a limit of one successful publish queue per minute. +This endpoint has a specific rate limit of one successful publish queue per minute. Required scope | `sites:write`
@@ -626,6 +634,8 @@ client = Webflow( ) client.sites.publish( site_id="580e63e98c9a982ac9b8b741", + custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], + publish_to_webflow_subdomain=False, ) ``` @@ -763,7 +773,9 @@ client.collections.list(
-Create a Collection for a site. +Create a Collection for a site with collection fields. + +Each collection includes the required _name_ and _slug_ fields, which are generated automatically. You can update the `displayName` of these fields, but the slug for them cannot be changed. Fields slugs are automatically converted to lowercase. Spaces in slugs are replaced with hyphens. Required scope | `cms:write`
@@ -780,7 +792,7 @@ Required scope | `cms:write`
```python -from webflow import Webflow +from webflow import ReferenceField, ReferenceFieldMetadata, StaticField, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -790,6 +802,29 @@ client.collections.create( display_name="Blog Posts", singular_name="Blog Post", slug="posts", + fields=[ + StaticField( + is_required=True, + type="PlainText", + display_name="Title", + help_text="The title of the blog post", + ), + StaticField( + is_required=True, + type="RichText", + display_name="Content", + help_text="The content of the blog post", + ), + ReferenceField( + is_required=True, + type="Reference", + display_name="Author", + help_text="The author of the blog post", + metadata=ReferenceFieldMetadata( + collection_id="23cc2d952d4e4631ffd4345d2743db4e", + ), + ), + ], ) ``` @@ -838,6 +873,14 @@ client.collections.create(
+**fields:** `typing.Optional[typing.Sequence[FieldCreate]]` — An array of custom fields to add to the collection + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -1032,6 +1075,8 @@ client = Webflow( client.pages.list( site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0", + limit=1, + offset=1, ) ``` @@ -1056,7 +1101,11 @@ client.pages.list(
-**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**locale_id:** `typing.Optional[str]` + +Unique identifier for a specific Locale. + +[Lear more about localization.](/data/v2.0.0/docs/working-with-localization)
@@ -1064,7 +1113,7 @@ client.pages.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -1072,7 +1121,7 @@ client.pages.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -1153,7 +1202,11 @@ client.pages.get_metadata(
-**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**locale_id:** `typing.Optional[str]` + +Unique identifier for a specific Locale. + +[Lear more about localization.](/data/v2.0.0/docs/working-with-localization)
@@ -1202,9 +1255,11 @@ Required scope | `pages:write`
```python -import datetime - -from webflow import PageOpenGraph, PageSeo, Webflow +from webflow import Webflow +from webflow.resources.pages import ( + PageMetadataWriteOpenGraph, + PageMetadataWriteSeo, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -1212,32 +1267,18 @@ client = Webflow( client.pages.update_page_settings( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", title="Guide to the Galaxy", slug="guide-to-the-galaxy", - created_on=datetime.datetime.fromisoformat( - "2024-03-11 10:42:00+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2024-03-11 10:42:42+00:00", - ), - archived=False, - draft=False, - can_branch=True, - is_branch=False, - seo=PageSeo( + seo=PageMetadataWriteSeo( title="The Ultimate Hitchhiker's Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", ), - open_graph=PageOpenGraph( + open_graph=PageMetadataWriteOpenGraph( title="Explore the Cosmos with The Ultimate Guide", title_copied=False, description="Dive deep into the mysteries of the universe with your guide to everything galactic.", description_copied=False, ), - page_locale_id="653fd9af6a07fc9cfd7a5e57", - published_path="/en-us/guide-to-the-galaxy", ) ``` @@ -1262,95 +1303,11 @@ client.pages.update_page_settings(
-**id:** `str` — Unique identifier for the Page - -
-
- -
-
- -**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. - -
-
- -
-
- -**site_id:** `typing.Optional[str]` — Unique identifier for the Site - -
-
- -
-
- -**title:** `typing.Optional[str]` — Title of the Page - -
-
- -
-
- -**slug:** `typing.Optional[str]` — slug of the Page (derived from title) - -
-
- -
-
- -**parent_id:** `typing.Optional[str]` — Identifier of the parent folder - -
-
- -
-
- -**collection_id:** `typing.Optional[str]` — Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. - -
-
- -
-
- -**created_on:** `typing.Optional[dt.datetime]` — The date the Page was created - -
-
- -
-
- -**last_updated:** `typing.Optional[dt.datetime]` — The date the Page was most recently updated - -
-
- -
-
- -**archived:** `typing.Optional[bool]` — Whether the Page has been archived - -
-
- -
-
- -**draft:** `typing.Optional[bool]` — Whether the Page is a draft - -
-
+**locale_id:** `typing.Optional[str]` -
-
+Unique identifier for a specific Locale. -**can_branch:** `typing.Optional[bool]` — Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) +[Lear more about localization.](/data/v2.0.0/docs/working-with-localization)
@@ -1358,7 +1315,7 @@ client.pages.update_page_settings(
-**is_branch:** `typing.Optional[bool]` — Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) +**title:** `typing.Optional[str]` — Title for the page
@@ -1366,23 +1323,12 @@ client.pages.update_page_settings(
-**is_members_only:** `typing.Optional[bool]` — Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) - -
-
- -
-
+**slug:** `typing.Optional[str]` -**seo:** `typing.Optional[PageSeo]` — SEO-related fields for the Page - -
-
+Slug for the page. -
-
-**open_graph:** `typing.Optional[PageOpenGraph]` — Open Graph fields for the Page +**Note:** Updating slugs in secondary locales is only supported in Advanced and Enterprise localization add-on plans.
@@ -1390,7 +1336,7 @@ client.pages.update_page_settings(
-**page_locale_id:** `typing.Optional[str]` — Unique ID of the page locale +**seo:** `typing.Optional[PageMetadataWriteSeo]` — SEO-related fields for the Page
@@ -1398,7 +1344,7 @@ client.pages.update_page_settings(
-**published_path:** `typing.Optional[str]` — Relative path of the published page URL +**open_graph:** `typing.Optional[PageMetadataWriteOpenGraph]` — Open Graph fields for the Page
@@ -1430,10 +1376,9 @@ client.pages.update_page_settings(
-Get static content from a static page. This includes text nodes, image nodes and component instances. -To retrieve the contents of components in the page use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint. +Get text and component instance content from a static page. -If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. +Localization Required scope | `pages:read`
@@ -1458,6 +1403,8 @@ client = Webflow( client.pages.get_content( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", + limit=1, + offset=1, ) ``` @@ -1482,7 +1429,11 @@ client.pages.get_content(
-**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**locale_id:** `typing.Optional[str]` + +Unique identifier for a specific Locale. + +[Lear more about localization.](/data/v2.0.0/docs/working-with-localization)
@@ -1490,7 +1441,7 @@ client.pages.get_content(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -1498,7 +1449,7 @@ client.pages.get_content(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -1533,8 +1484,9 @@ client.pages.get_content( This endpoint updates content on a static page in **secondary locales**. It supports updating up to 1000 nodes in a single request. Before making updates: -1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) endpoint to identify available content nodes and their types -2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint +1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) endpoint to identify available content nodes and their types. +2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. +3. DOM elements may include a `data-w-id` attribute. This attribute is used by Webflow to maintain custom attributes and links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. This endpoint is specifically for localized pages. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. @@ -1558,6 +1510,10 @@ Required scope | `pages:write` from webflow import ( ComponentInstanceNodePropertyOverridesWrite, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + Select, + SelectNodeWriteChoicesItem, + SubmitButtonNodeWrite, + TextInputNodeWrite, TextNodeWrite, Webflow, ) @@ -1577,6 +1533,28 @@ client.pages.update_static_content( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Don't Panic!

Always know where your towel is.

", ), + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInputNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButtonNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), ComponentInstanceNodePropertyOverridesWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ @@ -1680,6 +1658,9 @@ client = Webflow( ) client.components.list( site_id="580e63e98c9a982ac9b8b741", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) ``` @@ -1704,7 +1685,7 @@ client.components.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**branch_id:** `typing.Optional[str]` — Scope the operation to work on a specific branch.
@@ -1712,7 +1693,15 @@ client.components.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -1744,7 +1733,7 @@ client.components.list(
-Get static content from a component definition. This includes text nodes, image nodes and nested component instances. +Get static content from a component definition. This includes text nodes, image nodes, select nodes, text input nodes, submit button nodes, and nested component instances. To retrieve dynamic content set by component properties, use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. @@ -1773,6 +1762,9 @@ client.components.get_content( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) ``` @@ -1805,7 +1797,19 @@ client.components.get_content(
-**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**locale_id:** `typing.Optional[str]` + +Unique identifier for a specific Locale. + +[Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + +
+
+ +
+
+ +**branch_id:** `typing.Optional[str]` — Scope the operation to work on a specific branch.
@@ -1813,7 +1817,7 @@ client.components.get_content(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -1821,7 +1825,7 @@ client.components.get_content(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -1856,8 +1860,9 @@ client.components.get_content( This endpoint updates content within a component defintion for **secondary locales**. It supports updating up to 1000 nodes in a single request. Before making updates: -1. Use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint to identify available content nodes and their types -2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint +1. Use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint to identify available content nodes and their types. +2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. +3. DOM elements may include a `data-w-id` attribute. This attribute is used by Webflow to maintain custom attributes and links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. This endpoint is specifically for localizing component definitions. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. @@ -1881,6 +1886,10 @@ Required scope | `components:write` from webflow import ( ComponentInstanceNodePropertyOverridesWrite, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + Select, + SelectNodeWriteChoicesItem, + SubmitButtonNodeWrite, + TextInputNodeWrite, TextNodeWrite, Webflow, ) @@ -1892,6 +1901,7 @@ client.components.update_content( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", nodes=[ TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", @@ -1901,6 +1911,28 @@ client.components.update_content( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Don't Panic!

Always know where your towel is.

", ), + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInputNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButtonNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), ComponentInstanceNodePropertyOverridesWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ @@ -1955,7 +1987,19 @@ client.components.update_content(
-**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**locale_id:** `typing.Optional[str]` + +Unique identifier for a specific Locale. + +[Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + +
+
+ +
+
+ +**branch_id:** `typing.Optional[str]` — Scope the operation to work on a specific branch.
@@ -1987,9 +2031,9 @@ client.components.update_content(
-Get the property default values of a component definition. +Get the default property values of a component definition. -If you do not provide a Locale ID in your request, the response will return any properties that can be localized from the Primary locale. +If you do not include a `localeId` in your request, the response will return any properties that can be localized from the Primary locale. Required scope | `components:read`
@@ -2015,6 +2059,9 @@ client.components.get_properties( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) ``` @@ -2047,7 +2094,19 @@ client.components.get_properties(
-**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**locale_id:** `typing.Optional[str]` + +Unique identifier for a specific Locale. + +[Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + +
+
+ +
+
+ +**branch_id:** `typing.Optional[str]` — Scope the operation to work on a specific branch.
@@ -2055,7 +2114,7 @@ client.components.get_properties(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -2063,7 +2122,7 @@ client.components.get_properties(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -2095,12 +2154,13 @@ client.components.get_properties(
-Update the property default values of a component definition in a specificed locale. +Update the default property values of a component definition in a specificed locale. Before making updates: -1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify available properties +1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify properties that can be updated in a secondary locale. +2. Rich Text properties may include a `data-w-id` attribute. This attribute is used by Webflow to maintain links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. -The request requires a secondary locale ID. If a locale is missing, the request will not be processed and will result in an error. +The request requires a secondary locale ID. If a `localeId` is missing, the request will not be processed and will result in an error. Required scope | `components:write`
@@ -2127,6 +2187,7 @@ client.components.update_properties( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", properties=[ ComponentPropertiesWritePropertiesItem( property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", @@ -2177,7 +2238,19 @@ client.components.update_properties(
-**locale_id:** `typing.Optional[str]` — Unique identifier for a specific locale. Applicable, when using localization. +**locale_id:** `typing.Optional[str]` + +Unique identifier for a specific Locale. + +[Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + +
+
+ +
+
+ +**branch_id:** `typing.Optional[str]` — Scope the operation to work on a specific branch.
@@ -2210,14 +2283,11 @@ client.components.update_properties(
-List of scripts registered to a Site. - -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. -Additionally, Scripts can be remotely hosted, or registered as inline snippets. +Get a list of scripts that have been registered to a site. A site can have a maximum of 800 registered scripts. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read`
@@ -2289,14 +2359,11 @@ client.scripts.list(
-Add a script to a Site's Custom Code registry. - -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. -Additionally, Scripts can be remotely hosted, or registered as inline snippets. +Register a hosted script to a site. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write`
@@ -2412,13 +2479,11 @@ client.scripts.register_hosted(
-Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters. - -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. +Register an inline script to a site. Inline scripts are limited to 2000 characters. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write`
@@ -2534,7 +2599,7 @@ client.scripts.register_inline(
-List assets for a given site +List of assets uploaded to a site Required scope | `assets:read`
@@ -2558,6 +2623,8 @@ client = Webflow( ) client.assets.list( site_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) ``` @@ -2582,6 +2649,22 @@ client.assets.list(
+**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -2606,15 +2689,18 @@ client.assets.list(
-Create a new asset entry. +The first step in uploading an asset to a site. -This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. -You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) -request to the `uploadUrl` with the `uploadDetails` object as your header information in the request. +This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. - -Required scope | `assets:write` + +Use these properties in the header of a [POST request to Amazson s3](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) to complete the upload. + + +To learn more about how to upload assets to Webflow, see our [assets guide](/data/docs/working-with-assets). + + Required scope | `assets:write`
@@ -2710,7 +2796,7 @@ client.assets.create(
-Get an Asset +Get details about an asset Required scope | `assets:read`
@@ -2854,7 +2940,7 @@ client.assets.delete(
-Update an Asset +Update details of an Asset. Required scope | `assets:write`
@@ -3569,6 +3655,8 @@ client = Webflow( ) client.forms.list( site_id="580e63e98c9a982ac9b8b741", + limit=1, + offset=1, ) ``` @@ -3593,7 +3681,7 @@ client.forms.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -3601,7 +3689,7 @@ client.forms.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -3707,6 +3795,12 @@ client.forms.get( List form submissions for a given form + + When a form is used in a component definition, each instance of the form is considered a unique form. + + To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. + + Required scope | `forms:read`
@@ -3729,6 +3823,8 @@ client = Webflow( ) client.forms.list_submissions( form_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) ``` @@ -3753,7 +3849,7 @@ client.forms.list_submissions(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -3761,7 +3857,7 @@ client.forms.list_submissions(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -3853,7 +3949,7 @@ client.forms.get_submission(
-
client.forms.update_submission(...) +
client.forms.delete_submission(...)
@@ -3865,7 +3961,8 @@ client.forms.get_submission(
-Update hidden fields on a form submission +Delete a form submission + Required scope | `forms:write`
@@ -3887,7 +3984,7 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.forms.update_submission( +client.forms.delete_submission( form_submission_id="580e63e98c9a982ac9b8b741", ) @@ -3913,14 +4010,6 @@ client.forms.update_submission(
-**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -3933,8 +4022,7 @@ client.forms.update_submission(
-## Users -
client.users.list(...) +
client.forms.update_submission(...)
@@ -3946,9 +4034,9 @@ client.forms.update_submission(
-Get a list of users for a site +Update hidden fields on a form submission -Required scope | `users:read` +Required scope | `forms:write`
@@ -3968,8 +4056,8 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.list( - site_id="580e63e98c9a982ac9b8b741", +client.forms.update_submission( + form_submission_id="580e63e98c9a982ac9b8b741", ) ``` @@ -3986,23 +4074,7 @@ client.users.list(
-**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- -**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records - -
-
- -
-
- -**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**form_submission_id:** `str` — Unique identifier for a Form Submission
@@ -4010,13 +4082,7 @@ client.users.list(
-**sort:** `typing.Optional[UsersListRequestSort]` - -Sort string to use when ordering users - -Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). - -Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) +**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set
@@ -4036,7 +4102,8 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-
client.users.get(...) +## Products +
client.products.list(...)
@@ -4048,9 +4115,12 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-Get a User by ID +Retrieve all products for a site. + +Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product +will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. -Required scope | `users:read` +Required scope | `ecommerce:read`
@@ -4070,9 +4140,10 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.get( +client.products.list( site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) ``` @@ -4097,7 +4168,7 @@ client.users.get(
-**user_id:** `str` — Unique identifier for a User +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -4105,19 +4176,27 @@ client.users.get(
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
- -
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+ +
-
client.users.delete(...) +
client.products.create(...)
@@ -4129,9 +4208,16 @@ client.users.get(
-Delete a User by ID +Create a new ecommerce product and defaultSKU. A product, at minimum, must have a single SKU. + +To create a product with multiple SKUs: + - First, create a list of `sku-properties`, also known as [product options](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). For example, a T-shirt product may have a "color" `sku-property`, with a list of enum values: red, yellow, and blue, another `sku-property` may be "size", with a list of enum values: small, medium, and large. + - Once, a product is created with a list of `sku-properties`, Webflow will create a **default SKU**, which is always a combination of the first `enum` values of each `sku-property`. (e.g. Small - Red - T-Shirt) + - After creation, you can create additional SKUs for the product, using the [Create SKUs endpoint.](/data/reference/ecommerce/products/create-sku) -Required scope | `users:write` +Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + +Required scope | `ecommerce:write`
@@ -4146,14 +4232,88 @@ Required scope | `users:write`
```python -from webflow import Webflow +from webflow import ( + ProductFieldData, + SkuFieldData, + SkuFieldDataPrice, + SkuPropertyList, + SkuPropertyListEnumItem, + Webflow, +) +from webflow.resources.products import ( + ProductSkuCreateProduct, + ProductSkuCreateSku, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.delete( +client.products.create( site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", + publish_status="staging", + product=ProductSkuCreateProduct( + field_data=ProductFieldData( + name="Colorful T-shirt", + slug="colorful-t-shirt", + description="Our best-selling t-shirt available in multiple colors and sizes", + sku_properties=[ + SkuPropertyList( + id="color", + name="Color", + enum=[ + SkuPropertyListEnumItem( + id="red", + name="Red", + slug="red", + ), + SkuPropertyListEnumItem( + id="yellow", + name="Yellow", + slug="yellow", + ), + SkuPropertyListEnumItem( + id="blue", + name="Blue", + slug="blue", + ), + ], + ), + SkuPropertyList( + id="size", + name="Size", + enum=[ + SkuPropertyListEnumItem( + id="small", + name="Small", + slug="small", + ), + SkuPropertyListEnumItem( + id="medium", + name="Medium", + slug="medium", + ), + SkuPropertyListEnumItem( + id="large", + name="Large", + slug="large", + ), + ], + ), + ], + ), + ), + sku=ProductSkuCreateSku( + field_data=SkuFieldData( + name="Colorful T-shirt - Red Small", + slug="colorful-t-shirt-red-small", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", + ), + ), ) ``` @@ -4178,7 +4338,23 @@ client.users.delete(
-**user_id:** `str` — Unique identifier for a User +**product:** `ProductSkuCreateProduct` + +
+
+ +
+
+ +**sku:** `ProductSkuCreateSku` + +
+
+ +
+
+ +**publish_status:** `typing.Optional[PublishStatus]`
@@ -4198,7 +4374,7 @@ client.users.delete(
-
client.users.update(...) +
client.products.get(...)
@@ -4210,12 +4386,10 @@ client.users.delete(
-Update a User by ID - - Required scope | `users:write` +Retrieve a single product by its ID. All of its SKUs will also be +retrieved. -The email and password -fields cannot be updated using this endpoint +Required scope | `ecommerce:read`
@@ -4231,20 +4405,13 @@ fields cannot be updated using this endpoint ```python from webflow import Webflow -from webflow.resources.users import UsersUpdateRequestData client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.update( +client.products.get( site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", - data=UsersUpdateRequestData( - name="Some One", - accept_privacy=False, - accept_communications=False, - ), - access_groups=["webflowers", "platinum", "free-tier"], + product_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -4269,24 +4436,7 @@ client.users.update(
-**user_id:** `str` — Unique identifier for a User - -
-
- -
-
- -**data:** `typing.Optional[UsersUpdateRequestData]` - -
-
- -
-
- -**access_groups:** `typing.Optional[typing.Sequence[str]]` — An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. - +**product_id:** `str` — Unique identifier for a Product
@@ -4306,7 +4456,7 @@ client.users.update(
-
client.users.invite(...) +
client.products.update(...)
@@ -4318,11 +4468,11 @@ client.users.update(
-Create and invite a user with an email address. +Update an existing Product. -The user will be sent and invite via email, which they will need to accept in order to join paid any paid access group. +Updating an existing Product will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. -Required scope | `users:write` +Required scope | `ecommerce:write`
@@ -4342,10 +4492,9 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.users.invite( +client.products.update( site_id="580e63e98c9a982ac9b8b741", - email="some.one@home.com", - access_groups=["webflowers"], + product_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -4370,7 +4519,15 @@ client.users.invite(
-**email:** `str` — Email address of user to send invite to +**product_id:** `str` — Unique identifier for a Product + +
+
+ +
+
+ +**publish_status:** `typing.Optional[PublishStatus]`
@@ -4378,8 +4535,15 @@ client.users.invite(
-**access_groups:** `typing.Optional[typing.Sequence[str]]` — An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. +**product:** `typing.Optional[Product]` + +
+
+ +
+
+**sku:** `typing.Optional[Sku]`
@@ -4399,8 +4563,7 @@ client.users.invite(
-## AccessGroups -
client.access_groups.list(...) +
client.products.create_sku(...)
@@ -4412,9 +4575,11 @@ client.users.invite(
-Get a list of access groups for a site +Create additional SKUs to manage every [option and variant of your Product.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants) + +Creating SKUs through the API will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. -Required scope | `users:read` +Required scope | `ecommerce:write`
@@ -4429,13 +4594,40 @@ Required scope | `users:read`
```python -from webflow import Webflow +import datetime + +from webflow import Sku, SkuFieldData, SkuFieldDataPrice, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.access_groups.list( +client.products.create_sku( site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + skus=[ + Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ) + ], ) ``` @@ -4460,7 +4652,7 @@ client.access_groups.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**product_id:** `str` — Unique identifier for a Product
@@ -4468,7 +4660,7 @@ client.access_groups.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**skus:** `typing.Sequence[Sku]` — An array of the SKU data your are adding
@@ -4476,10 +4668,7 @@ client.access_groups.list(
-**sort:** `typing.Optional[AccessGroupsListRequestSort]` - -Sort string to use when ordering access groups -Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) +**publish_status:** `typing.Optional[PublishStatus]`
@@ -4499,8 +4688,7 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-## Products -
client.products.list(...) +
client.products.update_sku(...)
@@ -4512,12 +4700,11 @@ Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`)
-Retrieve all products for a site. +Update a specified SKU. -Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product -will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. +Updating an existing SKU will set the Product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. -Required scope | `ecommerce:read` +Required scope | `ecommerce:write`
@@ -4532,13 +4719,39 @@ Required scope | `ecommerce:read`
```python -from webflow import Webflow +import datetime + +from webflow import Sku, SkuFieldData, SkuFieldDataPrice, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.list( +client.products.update_sku( site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + sku_id="5e8518516e147040726cc415", + sku=Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ), ) ``` @@ -4563,7 +4776,23 @@ client.products.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**product_id:** `str` — Unique identifier for a Product + +
+
+ +
+
+ +**sku_id:** `str` — Unique identifier for a SKU + +
+
+ +
+
+ +**sku:** `Sku`
@@ -4571,7 +4800,7 @@ client.products.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**publish_status:** `typing.Optional[PublishStatus]`
@@ -4591,7 +4820,8 @@ client.products.list(
-
client.products.create(...) +## Orders +
client.orders.list(...)
@@ -4603,20 +4833,9 @@ client.products.list(
-Create a new product and SKU. - -When you create a product, you will always create a SKU, since a Product Item must have, at minimum, a single SKU. - -To create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large: - - Create parameters in `sku-properties`, also known as [product options and variants.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). - - A single `sku-property` would be `color`. Within the `color` property, list the various colors of T-shirts as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. - - Once, you've created a Product and its `sku-properties` with `enum` values, Webflow will create a **default SKU**, which will automatically be a combination of the first `sku-properties` you've created. - - In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. - - After you've created your product, you can create additional SKUs using the [Create SKU endpoint.](/data/reference/ecommerce/products/create-sku) - -Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. +List all orders created for a given site. -Required scope | `ecommerce:write` +Required scope | `ecommerce:read`
@@ -4636,8 +4855,11 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.create( +client.orders.list( site_id="580e63e98c9a982ac9b8b741", + status="pending", + offset=1, + limit=1, ) ``` @@ -4662,7 +4884,7 @@ client.products.create(
-**publish_status:** `typing.Optional[PublishStatus]` +**status:** `typing.Optional[OrdersListRequestStatus]` — Filter the orders by status
@@ -4670,7 +4892,7 @@ client.products.create(
-**product:** `typing.Optional[Product]` +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -4678,7 +4900,7 @@ client.products.create(
-**sku:** `typing.Optional[Sku]` +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -4698,7 +4920,7 @@ client.products.create(
-
client.products.get(...) +
client.orders.get(...)
@@ -4733,9 +4955,9 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.get( +client.orders.get( site_id="580e63e98c9a982ac9b8b741", - product_id="580e63fc8c9a982ac9b8b745", + order_id="5e8518516e147040726cc415", ) ``` @@ -4760,7 +4982,7 @@ client.products.get(
-**product_id:** `str` — Unique identifier for a Product +**order_id:** `str` — Unique identifier for an Order
@@ -4780,7 +5002,7 @@ client.products.get(
-
client.products.update(...) +
client.orders.update(...)
@@ -4792,9 +5014,9 @@ client.products.get(
-Update an existing Product. - -Updating an existing Product will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. +This API lets you update the fields, `comment`, `shippingProvider`, +and/or `shippingTracking` for a given order. All three fields can be +updated simultaneously or independently. Required scope | `ecommerce:write`
@@ -4816,9 +5038,9 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.update( +client.orders.update( site_id="580e63e98c9a982ac9b8b741", - product_id="580e63fc8c9a982ac9b8b745", + order_id="5e8518516e147040726cc415", ) ``` @@ -4843,7 +5065,7 @@ client.products.update(
-**product_id:** `str` — Unique identifier for a Product +**order_id:** `str` — Unique identifier for an Order
@@ -4851,7 +5073,7 @@ client.products.update(
-**publish_status:** `typing.Optional[PublishStatus]` +**comment:** `typing.Optional[str]` — Arbitrary data for your records
@@ -4859,7 +5081,7 @@ client.products.update(
-**product:** `typing.Optional[Product]` +**shipping_provider:** `typing.Optional[str]` — Company or method used to ship order
@@ -4867,7 +5089,15 @@ client.products.update(
-**sku:** `typing.Optional[Sku]` +**shipping_tracking:** `typing.Optional[str]` — Tracking number for order shipment + +
+
+ +
+
+ +**shipping_tracking_url:** `typing.Optional[str]` — URL to track order shipment
@@ -4887,7 +5117,7 @@ client.products.update(
-
client.products.create_sku(...) +
client.orders.update_fulfill(...)
@@ -4899,9 +5129,7 @@ client.products.update(
-Create additional SKUs to manage every [option and variant of your Product.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants) - -Creating SKUs through the API will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. +Updates an order's status to fulfilled Required scope | `ecommerce:write`
@@ -4918,15 +5146,14 @@ Required scope | `ecommerce:write`
```python -from webflow import Sku, Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.create_sku( +client.orders.update_fulfill( site_id="580e63e98c9a982ac9b8b741", - product_id="580e63fc8c9a982ac9b8b745", - skus=[Sku()], + order_id="5e8518516e147040726cc415", ) ``` @@ -4951,15 +5178,7 @@ client.products.create_sku(
-**product_id:** `str` — Unique identifier for a Product - -
-
- -
-
- -**skus:** `typing.Sequence[Sku]` — An array of the SKU data your are adding +**order_id:** `str` — Unique identifier for an Order
@@ -4967,7 +5186,7 @@ client.products.create_sku(
-**publish_status:** `typing.Optional[PublishStatus]` +**send_order_fulfilled_email:** `typing.Optional[bool]` — Whether or not the Order Fulfilled email should be sent
@@ -4987,7 +5206,7 @@ client.products.create_sku(
-
client.products.update_sku(...) +
client.orders.update_unfulfill(...)
@@ -4999,9 +5218,7 @@ client.products.create_sku(
-Update a specified SKU. - -Updating an existing SKU will set the Product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. +Updates an order's status to unfulfilled Required scope | `ecommerce:write`
@@ -5018,16 +5235,14 @@ Required scope | `ecommerce:write`
```python -from webflow import Sku, Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.products.update_sku( +client.orders.update_unfulfill( site_id="580e63e98c9a982ac9b8b741", - product_id="580e63fc8c9a982ac9b8b745", - sku_id="5e8518516e147040726cc415", - sku=Sku(), + order_id="5e8518516e147040726cc415", ) ``` @@ -5052,7 +5267,7 @@ client.products.update_sku(
-**product_id:** `str` — Unique identifier for a Product +**order_id:** `str` — Unique identifier for an Order
@@ -5060,48 +5275,23 @@ client.products.update_sku(
-**sku_id:** `str` — Unique identifier for a SKU +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
-
-
-**sku:** `Sku` -
+
+
client.orders.refund(...)
-**publish_status:** `typing.Optional[PublishStatus]` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
- - - - - - -
- -## Orders -
client.orders.list(...) -
-
- -#### 📝 Description +#### 📝 Description
@@ -5109,9 +5299,10 @@ client.products.update_sku(
-List all orders created for a given site. +This API will reverse a Stripe charge and refund an order back to a +customer. It will also set the order's status to `refunded`. -Required scope | `ecommerce:read` +Required scope | `ecommerce:write`
@@ -5131,8 +5322,9 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.list( +client.orders.refund( site_id="580e63e98c9a982ac9b8b741", + order_id="5e8518516e147040726cc415", ) ``` @@ -5157,15 +5349,7 @@ client.orders.list(
-**status:** `typing.Optional[OrdersListRequestStatus]` — Filter the orders by status - -
-
- -
-
- -**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**order_id:** `str` — Unique identifier for an Order
@@ -5173,7 +5357,7 @@ client.orders.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**reason:** `typing.Optional[OrdersRefundRequestReason]` — The reason for the refund
@@ -5193,7 +5377,8 @@ client.orders.list(
-
client.orders.get(...) +## Inventory +
client.inventory.list(...)
@@ -5205,8 +5390,7 @@ client.orders.list(
-Retrieve a single product by its ID. All of its SKUs will also be -retrieved. +List the current inventory levels for a particular SKU item. Required scope | `ecommerce:read`
@@ -5228,9 +5412,9 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.get( - site_id="580e63e98c9a982ac9b8b741", - order_id="5e8518516e147040726cc415", +client.inventory.list( + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", ) ``` @@ -5247,7 +5431,7 @@ client.orders.get(
-**site_id:** `str` — Unique identifier for a Site +**sku_collection_id:** `str` — Unique identifier for a SKU collection. Use the List Collections API to find this ID.
@@ -5255,7 +5439,7 @@ client.orders.get(
-**order_id:** `str` — Unique identifier for an Order +**sku_id:** `str` — Unique identifier for a SKU
@@ -5275,7 +5459,7 @@ client.orders.get(
-
client.orders.update(...) +
client.inventory.update(...)
@@ -5287,9 +5471,11 @@ client.orders.get(
-This API lets you update the fields, `comment`, `shippingProvider`, -and/or `shippingTracking` for a given order. All three fields can be -updated simultaneously or independently. +Updates the current inventory levels for a particular SKU item. + +Updates may be given in one or two methods, absolutely or incrementally. +- Absolute updates are done by setting `quantity` directly. +- Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. Required scope | `ecommerce:write`
@@ -5311,9 +5497,10 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.update( - site_id="580e63e98c9a982ac9b8b741", - order_id="5e8518516e147040726cc415", +client.inventory.update( + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", + inventory_type="infinite", ) ``` @@ -5330,15 +5517,7 @@ client.orders.update(
-**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- -**order_id:** `str` — Unique identifier for an Order +**sku_collection_id:** `str` — Unique identifier for a SKU collection. Use the List Collections API to find this ID.
@@ -5346,7 +5525,7 @@ client.orders.update(
-**comment:** `typing.Optional[str]` — Arbitrary data for your records +**sku_id:** `str` — Unique identifier for a SKU
@@ -5354,7 +5533,7 @@ client.orders.update(
-**shipping_provider:** `typing.Optional[str]` — Company or method used to ship order +**inventory_type:** `InventoryUpdateRequestInventoryType` — infinite or finite
@@ -5362,7 +5541,7 @@ client.orders.update(
-**shipping_tracking:** `typing.Optional[str]` — Tracking number for order shipment +**update_quantity:** `typing.Optional[float]` — Adds this quantity to currently store quantity. Can be negative.
@@ -5370,7 +5549,7 @@ client.orders.update(
-**shipping_tracking_url:** `typing.Optional[str]` — URL to track order shipment +**quantity:** `typing.Optional[float]` — Immediately sets quantity to this value.
@@ -5390,7 +5569,8 @@ client.orders.update(
-
client.orders.update_fulfill(...) +## Ecommerce +
client.ecommerce.get_settings(...)
@@ -5402,9 +5582,9 @@ client.orders.update(
-Updates an order's status to fulfilled +Retrieve ecommerce settings for a site. -Required scope | `ecommerce:write` +Required scope | `ecommerce:read`
@@ -5424,9 +5604,8 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.update_fulfill( +client.ecommerce.get_settings( site_id="580e63e98c9a982ac9b8b741", - order_id="5e8518516e147040726cc415", ) ``` @@ -5451,22 +5630,6 @@ client.orders.update_fulfill(
-**order_id:** `str` — Unique identifier for an Order - -
-
- -
-
- -**send_order_fulfilled_email:** `typing.Optional[bool]` — Whether or not the Order Fulfilled email should be sent - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -5479,7 +5642,8 @@ client.orders.update_fulfill(
-
client.orders.update_unfulfill(...) +## Collections Fields +
client.collections.fields.create(...)
@@ -5491,9 +5655,13 @@ client.orders.update_fulfill(
-Updates an order's status to unfulfilled +Create a custom field in a collection. -Required scope | `ecommerce:write` +Field validation is currently not available through the API. + +Bulk creation of fields is not supported with this endpoint. To add multiple fields at once, include them when you [create the collection.](/data/v2.0.0/reference/cms/collections/create) + +Required scope | `cms:write`
@@ -5508,14 +5676,24 @@ Required scope | `ecommerce:write`
```python -from webflow import Webflow +from webflow import ReferenceField, ReferenceFieldMetadata, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.update_unfulfill( - site_id="580e63e98c9a982ac9b8b741", - order_id="5e8518516e147040726cc415", +client.collections.fields.create( + collection_id="580e63fc8c9a982ac9b8b745", + request=ReferenceField( + id="562ac0395358780a1f5e6fbd", + is_editable=True, + is_required=False, + type="Reference", + display_name="Author", + help_text="Add the post author here", + metadata=ReferenceFieldMetadata( + collection_id="63692ab61fb2852f582ba8f5", + ), + ), ) ``` @@ -5532,7 +5710,7 @@ client.orders.update_unfulfill(
-**site_id:** `str` — Unique identifier for a Site +**collection_id:** `str` — Unique identifier for a Collection
@@ -5540,7 +5718,7 @@ client.orders.update_unfulfill(
-**order_id:** `str` — Unique identifier for an Order +**request:** `FieldCreate`
@@ -5560,7 +5738,7 @@ client.orders.update_unfulfill(
-
client.orders.refund(...) +
client.collections.fields.delete(...)
@@ -5572,10 +5750,9 @@ client.orders.update_unfulfill(
-This API will reverse a Stripe charge and refund an order back to a -customer. It will also set the order's status to `refunded`. +Delete a custom field in a collection. This endpoint does not currently support bulk deletion. -Required scope | `ecommerce:write` +Required scope | `cms:write`
@@ -5595,9 +5772,9 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.orders.refund( - site_id="580e63e98c9a982ac9b8b741", - order_id="5e8518516e147040726cc415", +client.collections.fields.delete( + collection_id="580e63fc8c9a982ac9b8b745", + field_id="580e63fc8c9a982ac9b8b745", ) ``` @@ -5614,15 +5791,7 @@ client.orders.refund(
-**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- -**order_id:** `str` — Unique identifier for an Order +**collection_id:** `str` — Unique identifier for a Collection
@@ -5630,7 +5799,7 @@ client.orders.refund(
-**reason:** `typing.Optional[OrdersRefundRequestReason]` — The reason for the refund +**field_id:** `str` — Unique identifier for a Field in a collection
@@ -5650,8 +5819,7 @@ client.orders.refund(
-## Inventory -
client.inventory.list(...) +
client.collections.fields.update(...)
@@ -5663,9 +5831,9 @@ client.orders.refund(
-List the current inventory levels for a particular SKU item. +Update a custom field in a collection. -Required scope | `ecommerce:read` +Required scope | `cms:write`
@@ -5685,9 +5853,12 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.inventory.list( +client.collections.fields.update( collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + field_id="580e63fc8c9a982ac9b8b745", + is_required=False, + display_name="Post Body", + help_text="Add the body of your post here", ) ``` @@ -5712,7 +5883,31 @@ client.inventory.list(
-**item_id:** `str` — Unique identifier for an Item +**field_id:** `str` — Unique identifier for a Field in a collection + +
+
+ +
+
+ +**is_required:** `typing.Optional[bool]` — Define whether a field is required in a collection + +
+
+ +
+
+ +**display_name:** `typing.Optional[str]` — The name of a field + +
+
+ +
+
+ +**help_text:** `typing.Optional[str]` — Additional text to help anyone filling out this field
@@ -5732,7 +5927,8 @@ client.inventory.list(
-
client.inventory.update(...) +## Collections Items +
client.collections.items.list_items(...)
@@ -5744,13 +5940,9 @@ client.inventory.list(
-Updates the current inventory levels for a particular SKU item. - -Updates may be given in one or two methods, absolutely or incrementally. -- Absolute updates are done by setting `quantity` directly. -- Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. +List of all Items within a Collection. -Required scope | `ecommerce:write` +Required scope | `CMS:read`
@@ -5770,10 +5962,15 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.inventory.update( +client.collections.items.list_items( collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", - inventory_type="infinite", + cms_locale_id="cmsLocaleId", + offset=1, + limit=1, + name="name", + slug="slug", + sort_by="lastPublished", + sort_order="asc", ) ``` @@ -5798,7 +5995,7 @@ client.inventory.update(
-**item_id:** `str` — Unique identifier for an Item +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string.
@@ -5806,7 +6003,7 @@ client.inventory.update(
-**inventory_type:** `InventoryUpdateRequestInventoryType` — infinite or finite +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -5814,7 +6011,7 @@ client.inventory.update(
-**update_quantity:** `typing.Optional[float]` — Adds this quantity to currently store quantity. Can be negative. +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -5822,7 +6019,39 @@ client.inventory.update(
-**quantity:** `typing.Optional[float]` — Immediately sets quantity to this value. +**name:** `typing.Optional[str]` — Filter by the exact name of the item(s) + +
+
+ +
+
+ +**slug:** `typing.Optional[str]` — Filter by the exact slug of the item + +
+
+ +
+
+ +**last_published:** `typing.Optional[ItemsListItemsRequestLastPublished]` — Filter by the last published date of the item(s) + +
+
+ +
+
+ +**sort_by:** `typing.Optional[ItemsListItemsRequestSortBy]` — Sort results by the provided value + +
+
+ +
+
+ +**sort_order:** `typing.Optional[ItemsListItemsRequestSortOrder]` — Sorts the results by asc or desc
@@ -5842,8 +6071,7 @@ client.inventory.update(
-## Ecommerce -
client.ecommerce.get_settings(...) +
client.collections.items.create_item(...)
@@ -5855,9 +6083,12 @@ client.inventory.update(
-Retrieve ecommerce settings for a site. +Create Item(s) in a Collection. -Required scope | `ecommerce:read` + +To create items across multiple locales, please use [this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) + +Required scope | `CMS:write`
@@ -5872,97 +6103,39 @@ Required scope | `ecommerce:read`
```python -from webflow import Webflow - -client = Webflow( - access_token="YOUR_ACCESS_TOKEN", -) -client.ecommerce.get_settings( - site_id="580e63e98c9a982ac9b8b741", +from webflow import ( + CollectionItemPostSingle, + CollectionItemPostSingleFieldData, + Webflow, ) - -``` -
-
- - - -#### ⚙️ Parameters - -
-
- -
-
- -**site_id:** `str` — Unique identifier for a Site - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - - - -
- -## Collections Fields -
client.collections.fields.create(...) -
-
- -#### 📝 Description - -
-
- -
-
- -Create a custom field in a collection. - -Slugs must be all lowercase letters without spaces. -If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will -convert the slug to lowercase and replace spaces with "-." - -Only some field types can be created through the API. -This endpoint does not currently support bulk creation. - -Required scope | `cms:write` -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from webflow import Webflow +from webflow.resources.collections.resources.items import MultipleItems client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.fields.create( +client.collections.items.create_item( collection_id="580e63fc8c9a982ac9b8b745", - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", + skip_invalid_files=True, + request=MultipleItems( + items=[ + CollectionItemPostSingle( + is_archived=False, + is_draft=False, + field_data=CollectionItemPostSingleFieldData( + name="Senior Data Analyst", + slug="senior-data-analyst", + ), + ), + CollectionItemPostSingle( + is_archived=False, + is_draft=False, + field_data=CollectionItemPostSingleFieldData( + name="Product Manager", + slug="product-manager", + ), + ), + ], + ), ) ``` @@ -5987,23 +6160,7 @@ client.collections.fields.create(
-**type:** `FieldCreateType` — Choose these appropriate field type for your collection data - -
-
- -
-
- -**display_name:** `str` — The name of a field - -
-
- -
-
- -**is_required:** `typing.Optional[bool]` — define whether a field is required in a collection +**request:** `ItemsCreateItemRequestBody`
@@ -6011,7 +6168,7 @@ client.collections.fields.create(
-**help_text:** `typing.Optional[str]` — Additional text to help anyone filling out this field +**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid.
@@ -6031,7 +6188,7 @@ client.collections.fields.create(
-
client.collections.fields.delete(...) +
client.collections.items.delete_items(...)
@@ -6043,9 +6200,11 @@ client.collections.fields.create(
-Delete a custom field in a collection. This endpoint does not currently support bulk deletion. +Delete Items from a Collection. -Required scope | `cms:write` +Items will only be deleted in the primary locale unless a `cmsLocaleId` is included in the request. + +Required scope | `CMS:write`
@@ -6061,13 +6220,20 @@ Required scope | `cms:write` ```python from webflow import Webflow +from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsRequestItemsItem, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.fields.delete( +client.collections.items.delete_items( collection_id="580e63fc8c9a982ac9b8b745", - field_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) ``` @@ -6092,7 +6258,7 @@ client.collections.fields.delete(
-**field_id:** `str` — Unique identifier for a Field in a collection +**items:** `typing.Sequence[ItemsDeleteItemsRequestItemsItem]`
@@ -6112,7 +6278,7 @@ client.collections.fields.delete(
-
client.collections.fields.update(...) +
client.collections.items.update_items(...)
@@ -6124,9 +6290,13 @@ client.collections.fields.delete(
-Update a custom field in a collection. +Update a single item or multiple items in a Collection. -Required scope | `cms:write` +The limit for this endpoint is 100 items. + +Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. + +Required scope | `CMS:write`
@@ -6141,17 +6311,38 @@ Required scope | `cms:write`
```python -from webflow import Webflow +from webflow import ( + CollectionItemWithIdInput, + CollectionItemWithIdInputFieldData, + Webflow, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.fields.update( +client.collections.items.update_items( collection_id="580e63fc8c9a982ac9b8b745", - field_id="580e63fc8c9a982ac9b8b745", - is_required=False, - display_name="Post Body", - help_text="Add the body of your post here", + skip_invalid_files=True, + items=[ + CollectionItemWithIdInput( + id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, + field_data=CollectionItemWithIdInputFieldData( + name="Senior Data Analyst", + slug="senior-data-analyst", + ), + ), + CollectionItemWithIdInput( + id="580e64008c9a982ac9b8b754", + is_archived=False, + is_draft=False, + field_data=CollectionItemWithIdInputFieldData( + name="Product Manager", + slug="product-manager", + ), + ), + ], ) ``` @@ -6176,23 +6367,7 @@ client.collections.fields.update(
-**field_id:** `str` — Unique identifier for a Field in a collection - -
-
- -
-
- -**is_required:** `typing.Optional[bool]` — Define whether a field is required in a collection - -
-
- -
-
- -**display_name:** `typing.Optional[str]` — The name of a field +**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid.
@@ -6200,7 +6375,7 @@ client.collections.fields.update(
-**help_text:** `typing.Optional[str]` — Additional text to help anyone filling out this field +**items:** `typing.Optional[typing.Sequence[CollectionItemWithIdInput]]`
@@ -6220,8 +6395,7 @@ client.collections.fields.update(
-## Collections Items -
client.collections.items.list_items(...) +
client.collections.items.list_items_live(...)
@@ -6233,7 +6407,11 @@ client.collections.fields.update(
-List of all Items within a Collection. +List all published items in a collection. + + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + Required scope | `CMS:read`
@@ -6255,8 +6433,15 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.list_items( +client.collections.items.list_items_live( collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_id="cmsLocaleId", + offset=1, + limit=1, + name="name", + slug="slug", + sort_by="lastPublished", + sort_order="asc", ) ``` @@ -6289,7 +6474,7 @@ client.collections.items.list_items(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -6297,7 +6482,7 @@ client.collections.items.list_items(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -6305,7 +6490,7 @@ client.collections.items.list_items(
-**name:** `typing.Optional[str]` — The name of the item(s) +**name:** `typing.Optional[str]` — Filter by the exact name of the item(s)
@@ -6313,7 +6498,7 @@ client.collections.items.list_items(
-**slug:** `typing.Optional[str]` — The slug of the item +**slug:** `typing.Optional[str]` — Filter by the exact slug of the item
@@ -6321,7 +6506,7 @@ client.collections.items.list_items(
-**sort_by:** `typing.Optional[ItemsListItemsRequestSortBy]` — Sort results by the provided value +**last_published:** `typing.Optional[ItemsListItemsLiveRequestLastPublished]` — Filter by the last published date of the item(s)
@@ -6329,7 +6514,15 @@ client.collections.items.list_items(
-**sort_order:** `typing.Optional[ItemsListItemsRequestSortOrder]` — Sorts the results by asc or desc +**sort_by:** `typing.Optional[ItemsListItemsLiveRequestSortBy]` — Sort results by the provided value + +
+
+ +
+
+ +**sort_order:** `typing.Optional[ItemsListItemsLiveRequestSortOrder]` — Sorts the results by asc or desc
@@ -6349,7 +6542,7 @@ client.collections.items.list_items(
-
client.collections.items.create_item(...) +
client.collections.items.create_item_live(...)
@@ -6361,10 +6554,11 @@ client.collections.items.list_items(
-Create Item(s) in a Collection. +Create item(s) in a collection that will be immediately published to the live site. -To create items across multiple locales, please use [this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) +To create items across multiple locales, [please use this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) + Required scope | `CMS:write`
@@ -6381,32 +6575,29 @@ Required scope | `CMS:write`
```python -from webflow import ( - CollectionItemPostSingle, - CollectionItemPostSingleFieldData, - Webflow, -) -from webflow.resources.collections.resources.items import MultipleItems +from webflow import CollectionItem, CollectionItemFieldData, Webflow +from webflow.resources.collections.resources.items import MultipleLiveItems client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.create_item( +client.collections.items.create_item_live( collection_id="580e63fc8c9a982ac9b8b745", - request=MultipleItems( + skip_invalid_files=True, + request=MultipleLiveItems( items=[ - CollectionItemPostSingle( + CollectionItem( is_archived=False, is_draft=False, - field_data=CollectionItemPostSingleFieldData( + field_data=CollectionItemFieldData( name="Senior Data Analyst", slug="senior-data-analyst", ), ), - CollectionItemPostSingle( + CollectionItem( is_archived=False, is_draft=False, - field_data=CollectionItemPostSingleFieldData( + field_data=CollectionItemFieldData( name="Product Manager", slug="product-manager", ), @@ -6437,7 +6628,15 @@ client.collections.items.create_item(
-**request:** `ItemsCreateItemRequest` +**request:** `ItemsCreateItemLiveRequestBody` + +
+
+ +
+
+ +**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid.
@@ -6457,7 +6656,7 @@ client.collections.items.create_item(
-
client.collections.items.delete_items(...) +
client.collections.items.delete_items_live(...)
@@ -6469,9 +6668,9 @@ client.collections.items.create_item(
-Delete Items from a Collection. +Unpublish up to 100 items from the live site and set the `isDraft` property to `true`. -**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be deleted only in the primary locale. +Items will only be unpublished in the primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write`
@@ -6489,12 +6688,20 @@ Required scope | `CMS:write` ```python from webflow import Webflow +from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsLiveRequestItemsItem, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.delete_items( +client.collections.items.delete_items_live( collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsLiveRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) ``` @@ -6519,7 +6726,7 @@ client.collections.items.delete_items(
-**items:** `typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]]` +**items:** `typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]`
@@ -6539,7 +6746,7 @@ client.collections.items.delete_items(
-
client.collections.items.update_items(...) +
client.collections.items.update_items_live(...)
@@ -6551,9 +6758,9 @@ client.collections.items.delete_items(
-Update a single item or multiple items (up to 100) in a Collection. +Update a single published item or multiple published items (up to 100) in a Collection -**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. +Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write`
@@ -6579,8 +6786,9 @@ from webflow import ( client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.update_items( +client.collections.items.update_items_live( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, items=[ CollectionItemWithIdInput( id="66f6ed9576ddacf3149d5ea6", @@ -6639,6 +6847,14 @@ client.collections.items.update_items(
+**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + +
+
+ +
+
+ **items:** `typing.Optional[typing.Sequence[CollectionItemWithIdInput]]`
@@ -6659,7 +6875,7 @@ client.collections.items.update_items(
-
client.collections.items.list_items_live(...) +
client.collections.items.create_items(...)
@@ -6671,12 +6887,17 @@ client.collections.items.update_items(
-List of all live Items within a Collection. +Create an item or multiple items in a CMS Collection across multiple corresponding locales. -Required scope | `CMS:read` -
-
-
+ + - This endpoint can create up to 100 items in a request. + - If the `cmsLocaleIds` parameter is not included in the request, an item will only be created in the primary locale. + + +Required scope | `CMS:write` + +
+ #### 🔌 Usage @@ -6689,12 +6910,25 @@ Required scope | `CMS:read` ```python from webflow import Webflow +from webflow.resources.collections.resources.items import SingleCmsItem client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.list_items_live( +client.collections.items.create_items( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, + cms_locale_ids=[ + "66f6e966c9e1dc700a857ca3", + "66f6e966c9e1dc700a857ca4", + "66f6e966c9e1dc700a857ca5", + ], + is_archived=False, + is_draft=False, + field_data=SingleCmsItem( + name="Don’t Panic", + slug="dont-panic", + ), ) ``` @@ -6719,23 +6953,7 @@ client.collections.items.list_items_live(
-**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - -
-
- -
-
- -**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records - -
-
- -
-
- -**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**field_data:** `CreateBulkCollectionItemRequestBodyFieldData`
@@ -6743,7 +6961,7 @@ client.collections.items.list_items_live(
-**name:** `typing.Optional[str]` — The name of the item(s) +**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid.
@@ -6751,7 +6969,7 @@ client.collections.items.list_items_live(
-**slug:** `typing.Optional[str]` — The slug of the item +**cms_locale_ids:** `typing.Optional[typing.Sequence[str]]` — Array of identifiers for the locales where the item will be created
@@ -6759,7 +6977,7 @@ client.collections.items.list_items_live(
-**sort_by:** `typing.Optional[ItemsListItemsLiveRequestSortBy]` — Sort results by the provided value +**is_archived:** `typing.Optional[bool]` — Indicates whether the item is archived.
@@ -6767,7 +6985,7 @@ client.collections.items.list_items_live(
-**sort_order:** `typing.Optional[ItemsListItemsLiveRequestSortOrder]` — Sorts the results by asc or desc +**is_draft:** `typing.Optional[bool]` — Indicates whether the item is in draft state.
@@ -6787,7 +7005,7 @@ client.collections.items.list_items_live(
-
client.collections.items.create_item_live(...) +
client.collections.items.get_item(...)
@@ -6799,13 +7017,9 @@ client.collections.items.list_items_live(
-Create live Item(s) in a Collection. The Item(s) will be published to the live site. - - -To create items across multiple locales, [please use this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) - +Get details of a selected Collection Item. -Required scope | `CMS:write` +Required scope | `CMS:read`
@@ -6820,34 +7034,15 @@ Required scope | `CMS:write`
```python -from webflow import CollectionItem, CollectionItemFieldData, Webflow -from webflow.resources.collections.resources.items import MultipleLiveItems +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.create_item_live( +client.collections.items.get_item( collection_id="580e63fc8c9a982ac9b8b745", - request=MultipleLiveItems( - items=[ - CollectionItem( - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Senior Data Analyst", - slug="senior-data-analyst", - ), - ), - CollectionItem( - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Product Manager", - slug="product-manager", - ), - ), - ], - ), + item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) ``` @@ -6872,7 +7067,15 @@ client.collections.items.create_item_live(
-**request:** `ItemsCreateItemLiveRequest` +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string.
@@ -6892,7 +7095,7 @@ client.collections.items.create_item_live(
-
client.collections.items.delete_items_live(...) +
client.collections.items.delete_item(...)
@@ -6904,9 +7107,7 @@ client.collections.items.create_item_live(
-Remove an item or multiple items (up to 100 items) from the live site. Deleting published items will unpublish the items from the live site and set them to draft. - -**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be unpublished only in the primary locale. +Delete an item from a collection. Required scope | `CMS:write`
@@ -6928,8 +7129,10 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.delete_items_live( +client.collections.items.delete_item( collection_id="580e63fc8c9a982ac9b8b745", + item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) ``` @@ -6954,7 +7157,15 @@ client.collections.items.delete_items_live(
-**items:** `typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]]` +**item_id:** `str` — Unique identifier for an Item + +
+
+ +
+
+ +**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string.
@@ -6974,7 +7185,7 @@ client.collections.items.delete_items_live(
-
client.collections.items.update_items_live(...) +
client.collections.items.update_item(...)
@@ -6986,9 +7197,7 @@ client.collections.items.delete_items_live(
-Update a single live item or multiple live items (up to 100) in a Collection - -**Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. +Update a selected Item in a Collection. Required scope | `CMS:write`
@@ -7005,51 +7214,21 @@ Required scope | `CMS:write`
```python -from webflow import ( - CollectionItemWithIdInput, - CollectionItemWithIdInputFieldData, - Webflow, -) +from webflow import CollectionItemPatchSingleFieldData, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.update_items_live( +client.collections.items.update_item( collection_id="580e63fc8c9a982ac9b8b745", - items=[ - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5ea6", - cms_locale_id="66f6e966c9e1dc700a857ca5", - field_data=CollectionItemWithIdInputFieldData( - name="Ne Paniquez Pas", - slug="ne-paniquez-pas", - ), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5ea6", - cms_locale_id="66f6e966c9e1dc700a857ca4", - field_data=CollectionItemWithIdInputFieldData( - name="No Entrar en Pánico", - slug="no-entrar-en-panico", - ), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5eaa", - cms_locale_id="66f6e966c9e1dc700a857ca5", - field_data=CollectionItemWithIdInputFieldData( - name="Au Revoir et Merci pour Tous les Poissons", - slug="au-revoir-et-merci", - ), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5eaa", - cms_locale_id="66f6e966c9e1dc700a857ca4", - field_data=CollectionItemWithIdInputFieldData( - name="Hasta Luego y Gracias por Todo el Pescado", - slug="hasta-luego-y-gracias", - ), - ), - ], + item_id="580e64008c9a982ac9b8b754", + skip_invalid_files=True, + is_archived=False, + is_draft=False, + field_data=CollectionItemPatchSingleFieldData( + name="The Hitchhiker's Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", + ), ) ``` @@ -7074,7 +7253,7 @@ client.collections.items.update_items_live(
-**items:** `typing.Optional[typing.Sequence[CollectionItemWithIdInput]]` +**item_id:** `str` — Unique identifier for an Item
@@ -7082,87 +7261,39 @@ client.collections.items.update_items_live(
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. +**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid.
-
-
- - -
-
-
-
client.collections.items.create_items(...)
-#### 📝 Description - -
-
+**id:** `typing.Optional[str]` — Unique identifier for the Item + +
+
-Create an item or multiple items in a CMS Collection across multiple corresponding locales. - -**Notes:** - - This endpoint can create up to 100 items in a request. - - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. - -Required scope | `CMS:write` -
-
+**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item +
-#### 🔌 Usage - -
-
-
-```python -from webflow import Webflow -from webflow.resources.collections.resources.items import SingleCmsItem - -client = Webflow( - access_token="YOUR_ACCESS_TOKEN", -) -client.collections.items.create_items( - collection_id="580e63fc8c9a982ac9b8b745", - cms_locale_ids=[ - "66f6e966c9e1dc700a857ca3", - "66f6e966c9e1dc700a857ca4", - "66f6e966c9e1dc700a857ca5", - ], - is_archived=False, - is_draft=False, - field_data=SingleCmsItem( - name="Don’t Panic", - slug="dont-panic", - ), -) - -``` -
-
+**last_published:** `typing.Optional[str]` — The date the item was last published +
-#### ⚙️ Parameters - -
-
-
-**collection_id:** `str` — Unique identifier for a Collection +**last_updated:** `typing.Optional[str]` — The date the item was last updated
@@ -7170,7 +7301,7 @@ client.collections.items.create_items(
-**field_data:** `CreateBulkCollectionItemRequestBodyFieldData` +**created_on:** `typing.Optional[str]` — The date the item was created
@@ -7178,7 +7309,7 @@ client.collections.items.create_items(
-**cms_locale_ids:** `typing.Optional[typing.Sequence[str]]` — Array of identifiers for the locales where the item will be created +**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived
@@ -7186,7 +7317,7 @@ client.collections.items.create_items(
-**is_archived:** `typing.Optional[bool]` — Indicates whether the item is archived. +**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft
@@ -7194,7 +7325,7 @@ client.collections.items.create_items(
-**is_draft:** `typing.Optional[bool]` — Indicates whether the item is in draft state. +**field_data:** `typing.Optional[CollectionItemPatchSingleFieldData]`
@@ -7214,7 +7345,7 @@ client.collections.items.create_items(
-
client.collections.items.get_item(...) +
client.collections.items.get_item_live(...)
@@ -7226,7 +7357,11 @@ client.collections.items.create_items(
-Get details of a selected Collection Item. +Get details of a selected Collection live Item. + + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + Required scope | `CMS:read`
@@ -7248,9 +7383,10 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.get_item( +client.collections.items.get_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) ``` @@ -7303,7 +7439,7 @@ client.collections.items.get_item(
-
client.collections.items.delete_item(...) +
client.collections.items.delete_item_live(...)
@@ -7315,7 +7451,9 @@ client.collections.items.get_item(
-Delete an Item from a Collection. This endpoint does not currently support bulk deletion. +Unpublish a live item from the site and set the `isDraft` property to `true`. + +For bulk unpublishing, please use [this endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) Required scope | `CMS:write`
@@ -7337,9 +7475,10 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.delete_item( +client.collections.items.delete_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) ``` @@ -7392,7 +7531,7 @@ client.collections.items.delete_item(
-
client.collections.items.update_item(...) +
client.collections.items.update_item_live(...)
@@ -7404,7 +7543,7 @@ client.collections.items.delete_item(
-Update a selected Item in a Collection. +Update a selected live Item in a Collection. The updates for this Item will be published to the live site. Required scope | `CMS:write`
@@ -7426,14 +7565,15 @@ from webflow import CollectionItemPatchSingleFieldData, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.update_item( +client.collections.items.update_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + skip_invalid_files=True, is_archived=False, is_draft=False, field_data=CollectionItemPatchSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", + name="The Hitchhiker's Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", ), ) @@ -7467,6 +7607,14 @@ client.collections.items.update_item(
+**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + +
+
+ +
+
+ **id:** `typing.Optional[str]` — Unique identifier for the Item
@@ -7543,7 +7691,7 @@ client.collections.items.update_item(
-
client.collections.items.get_item_live(...) +
client.collections.items.publish_item(...)
@@ -7555,9 +7703,9 @@ client.collections.items.update_item(
-Get details of a selected Collection live Item. +Publish an item or multiple items. -Required scope | `CMS:read` +Required scope | `cms:write`
@@ -7573,13 +7721,28 @@ Required scope | `CMS:read` ```python from webflow import Webflow +from webflow.resources.collections.resources.items import ( + ItemIDsWithLocales, + ItemsPublishItemRequestItemsItemsItem, +) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.get_item_live( +client.collections.items.publish_item( collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + request=ItemIDsWithLocales( + items=[ + ItemsPublishItemRequestItemsItemsItem( + id="643fd856d66b6528195ee2ca", + cms_locale_ids=[ + "653ad57de882f528b32e810e", + "6514390aea353fc691d69827", + "65143930ea353fc691d69cd8", + ], + ) + ], + ), ) ``` @@ -7604,7 +7767,983 @@ client.collections.items.get_item_live(
-**item_id:** `str` — Unique identifier for an Item +**request:** `ItemsPublishItemRequest` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+ +
+ + + + +
+ +## Pages Scripts +
client.pages.scripts.get_custom_code(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get all scripts applied to a page. + +Required scope | `custom_code:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.scripts.get_custom_code( + page_id="63c720f9347c2139b248e552", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.pages.scripts.upsert_custom_code(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Apply registered scripts to a page. If you have multiple scripts your App needs to apply or maintain on a page, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. + + + To apply a script to a page, the script must first be registered to a Site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + +Required scope | `custom_code:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import ScriptApply, Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.scripts.upsert_custom_code( + page_id="63c720f9347c2139b248e552", + scripts=[ + ScriptApply( + id="cms_slider", + location="header", + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location="header", + version="0.0.1", + ), + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page + +
+
+ +
+
+ +**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated + +
+
+ +
+
+ +**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.pages.scripts.delete_custom_code(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Remove all scripts from a page applied by the App. This endpoint will not remove scripts from the site's registered scripts. + +To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-pages/upsert-custom-code) endpoint. + +Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). + +Required scope | `custom_code:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.pages.scripts.delete_custom_code( + page_id="63c720f9347c2139b248e552", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**page_id:** `str` — Unique identifier for a Page + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Sites Redirects +
client.sites.redirects.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Fetch a list of all 301 redirect rules configured for a specific site. + +Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + +This endpoint requires an Enterprise workspace. + +Required scope: `sites:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.redirects.list( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.redirects.create(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Add a new 301 redirection rule to a site. + +This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. + +This endpoint requires an Enterprise workspace. + +Required scope: `sites:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.redirects.create( + site_id="580e63e98c9a982ac9b8b741", + id="42e1a2b7aa1a13f768a0042a", + from_url="/mostly-harmless", + to_url="/earth", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**id:** `typing.Optional[str]` — The ID of the specific redirect rule + +
+
+ +
+
+ +**from_url:** `typing.Optional[str]` — The source URL path that will be redirected. + +
+
+ +
+
+ +**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.redirects.delete(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Remove a 301 redirection rule from a site. + +This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + +This endpoint requires an Enterprise workspace. + +Required scope: `sites:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.redirects.delete( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**redirect_id:** `str` — Unique identifier site rediect + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.redirects.update(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update a 301 redirection rule from a site. + +This endpoint requires an Enterprise workspace. + +Required scope: `sites:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.redirects.update( + site_id="580e63e98c9a982ac9b8b741", + redirect_id="66c4cb9a20cac35ed19500e6", + id="42e1a2b7aa1a13f768a0042a", + from_url="/mostly-harmless", + to_url="/earth", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**redirect_id:** `str` — Unique identifier site rediect + +
+
+ +
+
+ +**id:** `typing.Optional[str]` — The ID of the specific redirect rule + +
+
+ +
+
+ +**from_url:** `typing.Optional[str]` — The source URL path that will be redirected. + +
+
+ +
+
+ +**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Sites Plans +
client.sites.plans.get_site_plan(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Get site plan details for the specified Site. + +This endpoint requires an Enterprise workspace. + +Required scope | `sites:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.plans.get_site_plan( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Sites RobotsTxt +
client.sites.robots_txt.get(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve the robots.txt configuration for various user agents. + +This endpoint requires an Enterprise workspace. + +Required scope: `site_config:read` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.robots_txt.get( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.robots_txt.put(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Replace the `robots.txt` configuration for various user agents. + +This endpoint requires an Enterprise workspace. + +Required scope | `site_config:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import RobotsRulesItem, Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.robots_txt.put( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**rules:** `typing.Optional[typing.Sequence[RobotsRulesItem]]` — List of rules for user agents. + +
+
+ +
+
+ +**sitemap:** `typing.Optional[str]` — URL to the sitemap. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.sites.robots_txt.delete(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Remove specific rules for a user-agent in your `robots.txt` file. To delete all rules for a user-agent, provide an empty rule set. This will remove the user-agent's entry entirely, leaving it subject to your site's default crawling behavior. + +**Note:** Deleting a user-agent with no rules will make the user-agent's access unrestricted unless other directives apply. + +This endpoint requires an Enterprise workspace. + +Required scope: `site_config:write` +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from webflow import RobotsRulesItem, Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.robots_txt.delete( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="*", + allows=["/public"], + disallows=["/bubbles"], + ) + ], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**rules:** `typing.Optional[typing.Sequence[RobotsRulesItem]]` — List of rules for user agents.
@@ -7612,7 +8751,7 @@ client.collections.items.get_item_live(
-**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. +**sitemap:** `typing.Optional[str]` — URL to the sitemap.
@@ -7632,7 +8771,7 @@ client.collections.items.get_item_live(
-
client.collections.items.delete_item_live(...) +
client.sites.robots_txt.patch(...)
@@ -7644,11 +8783,11 @@ client.collections.items.get_item_live(
-Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. +Update the `robots.txt` configuration for various user agents. -This endpoint does not currently support bulk deletion. +This endpoint requires an Enterprise workspace. -Required scope | `CMS:write` +Required scope | `site_config:write`
@@ -7663,14 +8802,21 @@ Required scope | `CMS:write`
```python -from webflow import Webflow +from webflow import RobotsRulesItem, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.delete_item_live( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", +client.sites.robots_txt.patch( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", ) ``` @@ -7687,7 +8833,7 @@ client.collections.items.delete_item_live(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -7695,7 +8841,7 @@ client.collections.items.delete_item_live(
-**item_id:** `str` — Unique identifier for an Item +**rules:** `typing.Optional[typing.Sequence[RobotsRulesItem]]` — List of rules for user agents.
@@ -7703,7 +8849,7 @@ client.collections.items.delete_item_live(
-**cms_locale_id:** `typing.Optional[str]` — Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. +**sitemap:** `typing.Optional[str]` — URL to the sitemap.
@@ -7723,7 +8869,8 @@ client.collections.items.delete_item_live(
-
client.collections.items.update_item_live(...) +## Sites WellKnown +
client.sites.well_known.put(...)
@@ -7735,9 +8882,20 @@ client.collections.items.delete_item_live(
-Update a selected live Item in a Collection. The updates for this Item will be published to the live site. +Upload a supported well-known file to a site. -Required scope | `CMS:write` +The current restrictions on well-known files are as follows: + - Each file must be smaller than 100kb + - Less than 30 total files + - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` + + + `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. + + +This endpoint requires an Enterprise workspace. + +Required scope: `site_config:write`
@@ -7752,20 +8910,16 @@ Required scope | `CMS:write`
```python -from webflow import CollectionItemPatchSingleFieldData, Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.update_item_live( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", - is_archived=False, - is_draft=False, - field_data=CollectionItemPatchSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", - ), +client.sites.well_known.put( + site_id="580e63e98c9a982ac9b8b741", + file_name="apple-app-site-association.txt", + file_data='{\n "applinks": {\n "apps": [],\n "details": [\n {\n "appID": "ABCDE12345.com.example.app",\n "paths": [ "/*", "/some/path/*" ]\n }\n ]\n }\n}\n', + content_type="application/json", ) ``` @@ -7782,7 +8936,7 @@ client.collections.items.update_item_live(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site
@@ -7790,7 +8944,7 @@ client.collections.items.update_item_live(
-**item_id:** `str` — Unique identifier for an Item +**file_name:** `str` — The name of the file
@@ -7798,7 +8952,7 @@ client.collections.items.update_item_live(
-**id:** `typing.Optional[str]` — Unique identifier for the Item +**file_data:** `str` — The contents of the file
@@ -7806,7 +8960,7 @@ client.collections.items.update_item_live(
-**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item +**content_type:** `typing.Optional[WellKnownFileContentType]` — The content type of the file. Defaults to application/json
@@ -7814,39 +8968,73 @@ client.collections.items.update_item_live(
-**last_published:** `typing.Optional[str]` — The date the item was last published +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
-
-
-**last_updated:** `typing.Optional[str]` — The date the item was last updated -
+
+
client.sites.well_known.delete(...)
-**created_on:** `typing.Optional[str]` — The date the item was created - +#### 📝 Description + +
+
+ +
+
+ +Delete existing well-known files from a site. + +This endpoint requires an Enterprise workspace. + +Required scope: `site_config:write`
+
+
+ +#### 🔌 Usage
-**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived - +
+
+ +```python +from webflow import Webflow + +client = Webflow( + access_token="YOUR_ACCESS_TOKEN", +) +client.sites.well_known.delete( + site_id="580e63e98c9a982ac9b8b741", +) + +``` +
+
+#### ⚙️ Parameters +
-**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft +
+
+ +**site_id:** `str` — Unique identifier for a Site
@@ -7854,7 +9042,7 @@ client.collections.items.update_item_live(
-**field_data:** `typing.Optional[CollectionItemPatchSingleFieldData]` +**file_names:** `typing.Optional[typing.Sequence[str]]` — A list of file names to delete
@@ -7874,7 +9062,8 @@ client.collections.items.update_item_live(
-
client.collections.items.publish_item(...) +## Sites ActivityLogs +
client.sites.activity_logs.list(...)
@@ -7886,9 +9075,11 @@ client.collections.items.update_item_live(
-Publish an item or multiple items. +Retrieve Activity Logs for a specific Site. -Required scope | `cms:write` +This endpoint requires an Enterprise workspace. + +Required scope: `site_activity:read`
@@ -7908,9 +9099,10 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.collections.items.publish_item( - collection_id="580e63fc8c9a982ac9b8b745", - item_ids=["itemIds"], +client.sites.activity_logs.list( + site_id="580e63e98c9a982ac9b8b741", + limit=1, + offset=1, ) ``` @@ -7927,7 +9119,15 @@ client.collections.items.publish_item(
-**collection_id:** `str` — Unique identifier for a Collection +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -7935,7 +9135,7 @@ client.collections.items.publish_item(
-**item_ids:** `typing.Sequence[str]` +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -7955,8 +9155,8 @@ client.collections.items.publish_item(
-## Pages Scripts -
client.pages.scripts.get_custom_code(...) +## Sites Comments +
client.sites.comments.list_comment_threads(...)
@@ -7968,15 +9168,13 @@ client.collections.items.publish_item(
-Get all registered scripts that have been applied to a specific Page. +List all comment threads for a site. -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. - -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + There may be a delay of up to 5 minutes before new comments appear in the system. + -Required scope | `custom_code:read` +Required scope | `comments:read`
@@ -7996,8 +9194,13 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.scripts.get_custom_code( - page_id="63c720f9347c2139b248e552", +client.sites.comments.list_comment_threads( + site_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", ) ``` @@ -8014,7 +9217,51 @@ client.pages.scripts.get_custom_code(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**locale_id:** `typing.Optional[str]` + +Unique identifier for a specific Locale. + +[Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + +
+
+ +
+
+ +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**sort_by:** `typing.Optional[CommentsListCommentThreadsRequestSortBy]` — Sort results by the provided value. Only allowed when sortOrder is provided. + +
+
+ +
+
+ +**sort_order:** `typing.Optional[CommentsListCommentThreadsRequestSortOrder]` — Sorts the results by asc or desc
@@ -8034,7 +9281,7 @@ client.pages.scripts.get_custom_code(
-
client.pages.scripts.upsert_custom_code(...) +
client.sites.comments.get_comment_thread(...)
@@ -8046,17 +9293,13 @@ client.pages.scripts.get_custom_code(
-Add a registered script to a Page. - -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. - -A site can have a maximum of 800 registered scripts. +Get details of a specific comment thread. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + There may be a delay of up to 5 minutes before new comments appear in the system. + -Required scope | `custom_code:write` +Required scope | `comments:read`
@@ -8071,26 +9314,19 @@ Required scope | `custom_code:write`
```python -from webflow import ScriptApply, Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.scripts.upsert_custom_code( - page_id="63c720f9347c2139b248e552", - scripts=[ - ScriptApply( - id="cms_slider", - location="header", - version="1.0.0", - attributes={"my-attribute": "some-value"}, - ), - ScriptApply( - id="alert", - location="header", - version="0.0.1", - ), - ], +client.sites.comments.get_comment_thread( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", ) ``` @@ -8107,7 +9343,7 @@ client.pages.scripts.upsert_custom_code(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site
@@ -8115,7 +9351,7 @@ client.pages.scripts.upsert_custom_code(
-**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page +**comment_thread_id:** `str` — Unique identifier for a Comment Thread
@@ -8123,7 +9359,11 @@ client.pages.scripts.upsert_custom_code(
-**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated +**locale_id:** `typing.Optional[str]` + +Unique identifier for a specific Locale. + +[Lear more about localization.](/data/v2.0.0/docs/working-with-localization)
@@ -8131,7 +9371,31 @@ client.pages.scripts.upsert_custom_code(
-**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**sort_by:** `typing.Optional[CommentsGetCommentThreadRequestSortBy]` — Sort results by the provided value. Only allowed when sortOrder is provided. + +
+
+ +
+
+ +**sort_order:** `typing.Optional[CommentsGetCommentThreadRequestSortOrder]` — Sorts the results by asc or desc
@@ -8151,7 +9415,7 @@ client.pages.scripts.upsert_custom_code(
-
client.pages.scripts.delete_custom_code(...) +
client.sites.comments.list_comment_replies(...)
@@ -8163,15 +9427,13 @@ client.pages.scripts.upsert_custom_code(
-Delete the custom code block that an app has created for a page +List all replies to a specific comment thread. -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. - -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + There may be a delay of up to 5 minutes before new comments appear in the system. + -Required scope | `custom_code:write` +Required scope | `comments:read`
@@ -8191,8 +9453,14 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.pages.scripts.delete_custom_code( - page_id="63c720f9347c2139b248e552", +client.sites.comments.list_comment_replies( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", ) ``` @@ -8209,7 +9477,59 @@ client.pages.scripts.delete_custom_code(
-**page_id:** `str` — Unique identifier for a Page +**site_id:** `str` — Unique identifier for a Site + +
+
+ +
+
+ +**comment_thread_id:** `str` — Unique identifier for a Comment Thread + +
+
+ +
+
+ +**locale_id:** `typing.Optional[str]` + +Unique identifier for a specific Locale. + +[Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + +
+
+ +
+
+ +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**sort_by:** `typing.Optional[CommentsListCommentRepliesRequestSortBy]` — Sort results by the provided value. Only allowed when sortOrder is provided. + +
+
+ +
+
+ +**sort_order:** `typing.Optional[CommentsListCommentRepliesRequestSortOrder]` — Sorts the results by asc or desc
@@ -8229,8 +9549,8 @@ client.pages.scripts.delete_custom_code(
-## Sites Redirects -
client.sites.redirects.list(...) +## Sites Scripts +
client.sites.scripts.get_custom_code(...)
@@ -8242,12 +9562,13 @@ client.pages.scripts.delete_custom_code(
-Fetch a list of all URL redirect rules configured for a specific site. - -Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. +Get all scripts applied to a site by the App. + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + -Required scope: `sites:read` +Required scope | `custom_code:read`
@@ -8267,7 +9588,7 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.redirects.list( +client.sites.scripts.get_custom_code( site_id="580e63e98c9a982ac9b8b741", ) @@ -8305,7 +9626,7 @@ client.sites.redirects.list(
-
client.sites.redirects.create(...) +
client.sites.scripts.upsert_custom_code(...)
@@ -8317,11 +9638,13 @@ client.sites.redirects.list(
-Add a new URL redirection rule to a site. +Apply registered scripts to a site. If you have multiple scripts your App needs to apply or maintain on a site, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. -This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + -Required scope: `sites:write` +Required scope | `custom_code:write`
@@ -8336,16 +9659,26 @@ Required scope: `sites:write`
```python -from webflow import Webflow +from webflow import ScriptApply, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.redirects.create( +client.sites.scripts.upsert_custom_code( site_id="580e63e98c9a982ac9b8b741", - id="42e1a2b7aa1a13f768a0042a", - from_url="/mostly-harmless", - to_url="/earth", + scripts=[ + ScriptApply( + id="cms_slider", + location="header", + version="1.0.0", + attributes={"my-attribute": "some-value"}, + ), + ScriptApply( + id="alert", + location="header", + version="0.0.1", + ), + ], ) ``` @@ -8370,7 +9703,7 @@ client.sites.redirects.create(
-**id:** `typing.Optional[str]` — The ID of the specific redirect rule +**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page
@@ -8378,7 +9711,7 @@ client.sites.redirects.create(
-**from_url:** `typing.Optional[str]` — The source URL path that will be redirected. +**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated
@@ -8386,7 +9719,7 @@ client.sites.redirects.create(
-**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected. +**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created
@@ -8406,7 +9739,7 @@ client.sites.redirects.create(
-
client.sites.redirects.delete(...) +
client.sites.scripts.delete_custom_code(...)
@@ -8418,9 +9751,13 @@ client.sites.redirects.create(
-Remove a URL redirection rule from a site. -This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. -Required scope: `sites:write` +Remove all scripts from a site applied by the App. This endpoint will not remove scripts from the site's registered scripts. + +To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-sites/upsert-custom-code) endpoint. + +Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). + +Required scope | `custom_code:write`
@@ -8440,9 +9777,8 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.redirects.delete( +client.sites.scripts.delete_custom_code( site_id="580e63e98c9a982ac9b8b741", - redirect_id="66c4cb9a20cac35ed19500e6", ) ``` @@ -8467,14 +9803,6 @@ client.sites.redirects.delete(
-**redirect_id:** `str` — Unique identifier site rediect - -
-
- -
-
- **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -8487,7 +9815,7 @@ client.sites.redirects.delete(
-
client.sites.redirects.update(...) +
client.sites.scripts.list_custom_code_blocks(...)
@@ -8499,8 +9827,15 @@ client.sites.redirects.delete(
-Update a URL redirection rule from a site. -Required scope: `sites:write` +Get a list of scripts that have been applied to a site and/or individual pages. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. + + See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + +Required scope | `custom_code:read`
@@ -8520,12 +9855,10 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.redirects.update( +client.sites.scripts.list_custom_code_blocks( site_id="580e63e98c9a982ac9b8b741", - redirect_id="66c4cb9a20cac35ed19500e6", - id="42e1a2b7aa1a13f768a0042a", - from_url="/mostly-harmless", - to_url="/earth", + offset=1, + limit=1, ) ``` @@ -8550,23 +9883,7 @@ client.sites.redirects.update(
-**redirect_id:** `str` — Unique identifier site rediect - -
-
- -
-
- -**id:** `typing.Optional[str]` — The ID of the specific redirect rule - -
-
- -
-
- -**from_url:** `typing.Optional[str]` — The source URL path that will be redirected. +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -8574,7 +9891,7 @@ client.sites.redirects.update(
-**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected. +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -8594,8 +9911,8 @@ client.sites.redirects.update(
-## Sites Plans -
client.sites.plans.get_site_plan(...) +## Sites Forms +
client.sites.forms.list_submissions_by_site(...)
@@ -8607,9 +9924,17 @@ client.sites.redirects.update(
-Get site plan details for the specified Site. +List all form submissions for a given site with the ability to filter submissions by a centralized `elementId`. -Required scope | `sites:read` +Add `elementId` when you want to filter form submissions to a specific form in a site. You can get the `elementId` from the [List forms endpoint](/data/reference/forms/forms/list) (displayed as `formElementId` in the response). + + +When a form is used in a Webflow component definition, each instance of the component will yield a unique form. Adding the `elementId` in this request ensures this API response includes all submissions from that core form, wherever that form is used in instantiated components. + + +Use the [List Form Submissions endpoint](/data/reference/forms/form-submissions/list-submissions) to list form submissions for a given form ID. + +Required scope | `forms:read`
@@ -8629,8 +9954,11 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.plans.get_site_plan( +client.sites.forms.list_submissions_by_site( site_id="580e63e98c9a982ac9b8b741", + element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0", + offset=1, + limit=1, ) ``` @@ -8655,6 +9983,30 @@ client.sites.plans.get_site_plan(
+**element_id:** `typing.Optional[str]` — Identifier for an element + +
+
+ +
+
+ +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -8667,8 +10019,7 @@ client.sites.plans.get_site_plan(
-## Sites ActivityLogs -
client.sites.activity_logs.list(...) +
client.sites.forms.list_submissions(...)
@@ -8680,7 +10031,11 @@ client.sites.plans.get_site_plan(
-Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` +List form submissions for a given form ID within a specific site. + +Use the [List Form Submissions by Site endpoint](/data/reference/forms/form-submissions/list-submissions-by-site) to list form submissions for a given site with the ability to filter by a `formElementId`. + +Required scope | `forms:read`
@@ -8700,8 +10055,11 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.activity_logs.list( +client.sites.forms.list_submissions( site_id="580e63e98c9a982ac9b8b741", + form_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) ``` @@ -8726,7 +10084,15 @@ client.sites.activity_logs.list(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**form_id:** `str` — Unique identifier for a Form + +
+
+ +
+
+ +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records
@@ -8734,7 +10100,7 @@ client.sites.activity_logs.list(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100)
@@ -8754,8 +10120,7 @@ client.sites.activity_logs.list(
-## Sites Scripts -
client.sites.scripts.get_custom_code(...) +
client.sites.forms.get_submission(...)
@@ -8767,11 +10132,9 @@ client.sites.activity_logs.list(
-Get all registered scripts that have been applied to a specific Site. +Get information about a form submission within a specific site. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). - -Required scope | `custom_code:read` +Required scope | `forms:read`
@@ -8791,8 +10154,9 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.scripts.get_custom_code( +client.sites.forms.get_submission( site_id="580e63e98c9a982ac9b8b741", + form_submission_id="580e63e98c9a982ac9b8b741", ) ``` @@ -8817,6 +10181,14 @@ client.sites.scripts.get_custom_code(
+**form_submission_id:** `str` — Unique identifier for a Form Submission + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -8829,7 +10201,7 @@ client.sites.scripts.get_custom_code(
-
client.sites.scripts.upsert_custom_code(...) +
client.sites.forms.delete_submission(...)
@@ -8841,15 +10213,9 @@ client.sites.scripts.get_custom_code(
-Add a registered script to a Site. - -In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered -to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate -`custom_code` endpoints. - -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). +Delete a form submission within a specific site. -Required scope | `custom_code:write` +Required scope | `forms:write`
@@ -8864,26 +10230,14 @@ Required scope | `custom_code:write`
```python -from webflow import ScriptApply, Webflow +from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.scripts.upsert_custom_code( +client.sites.forms.delete_submission( site_id="580e63e98c9a982ac9b8b741", - scripts=[ - ScriptApply( - id="cms_slider", - location="header", - version="1.0.0", - attributes={"my-attribute": "some-value"}, - ), - ScriptApply( - id="alert", - location="header", - version="0.0.1", - ), - ], + form_submission_id="580e63e98c9a982ac9b8b741", ) ``` @@ -8908,23 +10262,7 @@ client.sites.scripts.upsert_custom_code(
-**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page - -
-
- -
-
- -**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated - -
-
- -
-
- -**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created +**form_submission_id:** `str` — Unique identifier for a Form Submission
@@ -8944,7 +10282,7 @@ client.sites.scripts.upsert_custom_code(
-
client.sites.scripts.delete_custom_code(...) +
client.sites.forms.update_submission(...)
@@ -8956,11 +10294,9 @@ client.sites.scripts.upsert_custom_code(
-Delete the custom code block that an app created for a Site +Update hidden fields on a form submission within a specific site. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). - -Required scope | `custom_code:write` +Required scope | `forms:write`
@@ -8980,8 +10316,9 @@ from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.scripts.delete_custom_code( +client.sites.forms.update_submission( site_id="580e63e98c9a982ac9b8b741", + form_submission_id="580e63e98c9a982ac9b8b741", ) ``` @@ -9006,6 +10343,22 @@ client.sites.scripts.delete_custom_code(
+**form_submission_id:** `str` — Unique identifier for a Form Submission + +
+
+ +
+
+ +**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set + +
+
+ +
+
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
@@ -9018,7 +10371,8 @@ client.sites.scripts.delete_custom_code(
-
client.sites.scripts.list_custom_code_blocks(...) +## Workspaces AuditLogs +
client.workspaces.audit_logs.get_workspace_audit_logs(...)
@@ -9030,11 +10384,11 @@ client.sites.scripts.delete_custom_code(
-Get all instances of Custom Code applied to a Site or Pages. +Get audit logs for a workspace. -Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). +This endpoint requires an Enterprise workspace and a workspace token with the `workspace_activity:read` scope. Create a workspace token from your workspace dashboard integrations page to use this endpoint. -Required scope | `custom_code:read` +Required scope | `workspace_activity:read`
@@ -9049,13 +10403,25 @@ Required scope | `custom_code:read`
```python +import datetime + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) -client.sites.scripts.list_custom_code_blocks( - site_id="580e63e98c9a982ac9b8b741", +client.workspaces.audit_logs.get_workspace_audit_logs( + workspace_id_or_slug="hitchhikers-workspace", + limit=1, + offset=1, + sort_order="asc", + event_type="user_access", + from_=datetime.datetime.fromisoformat( + "2025-06-22 16:00:31+00:00", + ), + to=datetime.datetime.fromisoformat( + "2025-07-22 16:00:31+00:00", + ), ) ``` @@ -9072,7 +10438,39 @@ client.sites.scripts.list_custom_code_blocks(
-**site_id:** `str` — Unique identifier for a Site +**workspace_id_or_slug:** `str` — Unique identifier or slug for a Workspace + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — Maximum number of records to be returned (max limit: 100) + +
+
+ +
+
+ +**offset:** `typing.Optional[int]` — Offset used for pagination if the results have more than limit records + +
+
+ +
+
+ +**sort_order:** `typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder]` — Sorts the results by asc or desc + +
+
+ +
+
+ +**event_type:** `typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType]` — The event type to filter by
@@ -9080,7 +10478,7 @@ client.sites.scripts.list_custom_code_blocks(
-**offset:** `typing.Optional[float]` — Offset used for pagination if the results have more than limit records +**from_:** `typing.Optional[dt.datetime]` — The start date to filter by
@@ -9088,7 +10486,7 @@ client.sites.scripts.list_custom_code_blocks(
-**limit:** `typing.Optional[float]` — Maximum number of records to be returned (max limit: 100) +**to:** `typing.Optional[dt.datetime]` — The end date to filter by
diff --git a/src/webflow/__init__.py b/src/webflow/__init__.py index 0d82d59..4c00894 100644 --- a/src/webflow/__init__.py +++ b/src/webflow/__init__.py @@ -1,8 +1,6 @@ # This file was auto-generated by Fern from our API Definition. from .types import ( - AccessGroup, - AccessGroupList, Application, Asset, AssetFolder, @@ -20,6 +18,8 @@ BulkCollectionItemFieldData, Collection, CollectionItem, + CollectionItemChanged, + CollectionItemCreated, CollectionItemFieldData, CollectionItemList, CollectionItemListNoPagination, @@ -28,10 +28,31 @@ CollectionItemPatchSingleFieldData, CollectionItemPostSingle, CollectionItemPostSingleFieldData, + CollectionItemPublished, + CollectionItemRemoved, + CollectionItemRemovedPayload, + CollectionItemRemovedPayloadFieldData, + CollectionItemUnpublished, + CollectionItemUnpublishedPayload, + CollectionItemUnpublishedPayloadFieldData, CollectionItemWithIdInput, CollectionItemWithIdInputFieldData, CollectionList, CollectionListArrayItem, + Comment, + CommentPayload, + CommentPayloadAuthor, + CommentPayloadMentionedUsersItem, + CommentReply, + CommentReplyAuthor, + CommentReplyList, + CommentReplyListPagination, + CommentReplyMentionedUsersItem, + CommentThread, + CommentThreadAuthor, + CommentThreadList, + CommentThreadListPagination, + CommentThreadMentionedUsersItem, Component, ComponentDom, ComponentInstanceNodePropertyOverridesWrite, @@ -41,20 +62,26 @@ ComponentProperties, ComponentProperty, ComponentPropertyType, - ConflictErrorBody, + Conflict, CustomCodeBlock, CustomCodeBlockType, CustomCodeHostedResponse, CustomCodeInlineResponse, + CustomRole, + CustomRoleAuditLogItem, + CustomRoleAuditLogItemEventSubType, Dom, Domain, Domains, - DuplicateUserEmail, EcommerceSettings, Error, ErrorCode, Field, + FieldCreate, FieldType, + FieldValidations, + FieldValidationsAdditionalProperties, + FieldValidationsAdditionalPropertiesAdditionalProperties, ForbiddenErrorBody, Form, FormField, @@ -64,26 +91,43 @@ FormResponseSettings, FormSubmission, FormSubmissionList, + FormSubmissionTrigger, + FormSubmissionTriggerPayload, + FormSubmissionTriggerPayloadSchemaItem, + FormSubmissionTriggerPayloadSchemaItemFieldType, ImageNode, ImageNodeImage, InvalidDomain, InvalidScopes, InventoryItem, InventoryItemInventoryType, + ItemsListItemsLiveRequestLastPublished, + ItemsListItemsRequestLastPublished, ListCustomCodeBlocks, Locale, Locales, + Metadata, + MetadataOptionsItem, + NewOrder, NoDomains, Node, Node_ComponentInstance, Node_Image, + Node_SearchButton, + Node_Select, + Node_SubmitButton, Node_Text, + Node_TextInput, NotEnterprisePlanSite, NotEnterprisePlanWorkspace, + OptionField, Order, OrderAddress, OrderAddressJapanType, OrderAddressType, + OrderBillingAddress, + OrderBillingAddressJapanType, + OrderBillingAddressType, OrderCustomerInfo, OrderDisputeLastStatus, OrderDownloadFilesItem, @@ -94,15 +138,26 @@ OrderPurchasedItemVariantImage, OrderPurchasedItemVariantImageFile, OrderPurchasedItemVariantImageFileVariantsItem, + OrderShippingAddress, + OrderShippingAddressJapanType, + OrderShippingAddressType, OrderStatus, OrderTotals, OrderTotalsExtrasItem, OrderTotalsExtrasItemType, Page, + PageCreatedWebhook, + PageCreatedWebhookPayload, + PageDeletedWebhook, + PageDeletedWebhookPayload, PageList, + PageMetadataUpdatedWebhook, + PageMetadataUpdatedWebhookPayload, PageOpenGraph, PageSeo, Pagination, + Payload, + PayloadFieldData, PaypalDetails, Product, ProductAndSkUs, @@ -113,11 +168,26 @@ PublishStatus, Redirect, Redirects, + ReferenceField, + ReferenceFieldMetadata, + ReferenceFieldType, RegisteredScriptList, + Robots, + RobotsRulesItem, ScriptApply, ScriptApplyList, ScriptApplyLocation, Scripts, + SearchButtonNode, + SearchButtonNodeWrite, + Select, + SelectNode, + SelectNodeChoicesItem, + SelectNodeWriteChoicesItem, + SettingChange, + SettingChangeAuditLogItem, + SingleLocaleCreatedPayload, + SingleLocaleCreatedPayloadFieldData, Site, SiteActivityLogItem, SiteActivityLogItemEvent, @@ -125,9 +195,14 @@ SiteActivityLogItemUser, SiteActivityLogResponse, SiteDataCollectionType, + SiteMembership, + SiteMembershipAuditLogItem, + SiteMembershipAuditLogItemEventSubType, SitePlan, SitePlanId, SitePlanName, + SitePublish, + SitePublishPayload, Sites, Sku, SkuFieldData, @@ -141,27 +216,58 @@ SkuPropertyList, SkuPropertyListEnumItem, SkuValueList, + StaticField, + StaticFieldType, StripeCard, StripeCardBrand, StripeCardExpires, StripeDetails, + SubmitButtonNode, + SubmitButtonNodeWrite, Text, + TextInputNode, + TextInputNodeWrite, TextNode, TextNodeText, TextNodeWrite, TriggerType, - User, - UserAccessGroupsItem, - UserAccessGroupsItemType, - UserData, - UserDataData, - UserLimitReached, - UserList, - UserStatus, - UsersNotEnabled, + UpdatedOrder, + UserAccess, + UserAccessAuditLogItem, + UserAccessAuditLogItemEventSubType, Webhook, WebhookFilter, WebhookList, + WorkspaceAuditLogItem, + WorkspaceAuditLogItemActor, + WorkspaceAuditLogItemPayloadSettingChangeMethod, + WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess, + WorkspaceAuditLogItemPayloadSiteMembershipMethod, + WorkspaceAuditLogItemPayloadSiteMembershipSite, + WorkspaceAuditLogItemPayloadSiteMembershipTargetUser, + WorkspaceAuditLogItemPayloadSiteMembershipUserType, + WorkspaceAuditLogItemPayloadUserAccessMethod, + WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod, + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem, + WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, + WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod, + WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, + WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType, + WorkspaceAuditLogItemWorkspace, + WorkspaceAuditLogItem_CustomRole, + WorkspaceAuditLogItem_SiteMembership, + WorkspaceAuditLogItem_UserAccess, + WorkspaceAuditLogItem_WorkspaceInvitation, + WorkspaceAuditLogItem_WorkspaceMembership, + WorkspaceAuditLogItem_WorkspaceSetting, + WorkspaceAuditLogResponse, + WorkspaceInvitation, + WorkspaceInvitationAuditLogItem, + WorkspaceInvitationAuditLogItemEventSubType, + WorkspaceMembership, + WorkspaceMembershipAuditLogItem, + WorkspaceMembershipAuditLogItemEventSubType, ) from .errors import ( BadRequestError, @@ -173,21 +279,22 @@ UnauthorizedError, ) from .resources import ( - AccessGroupsListRequestSort, ComponentDomWriteNodesItem, ComponentPropertiesWritePropertiesItem, ComponentsUpdateContentResponse, ComponentsUpdatePropertiesResponse, + EcommInventoryChangedPayload, InventoryUpdateRequestInventoryType, OrdersListRequestStatus, OrdersRefundRequestReason, PageDomWriteNodesItem, + PageMetadataWriteOpenGraph, + PageMetadataWriteSeo, + ProductSkuCreateProduct, + ProductSkuCreateSku, ProductsCreateSkuResponse, SitesPublishResponse, UpdateStaticContentResponse, - UsersListRequestSort, - UsersUpdateRequestData, - access_groups, assets, collections, components, @@ -200,17 +307,14 @@ scripts, sites, token, - users, webhooks, + workspaces, ) from .client import AsyncWebflow, Webflow from .environment import WebflowEnvironment from .version import __version__ __all__ = [ - "AccessGroup", - "AccessGroupList", - "AccessGroupsListRequestSort", "Application", "Asset", "AssetFolder", @@ -230,6 +334,8 @@ "BulkCollectionItemFieldData", "Collection", "CollectionItem", + "CollectionItemChanged", + "CollectionItemCreated", "CollectionItemFieldData", "CollectionItemList", "CollectionItemListNoPagination", @@ -238,10 +344,31 @@ "CollectionItemPatchSingleFieldData", "CollectionItemPostSingle", "CollectionItemPostSingleFieldData", + "CollectionItemPublished", + "CollectionItemRemoved", + "CollectionItemRemovedPayload", + "CollectionItemRemovedPayloadFieldData", + "CollectionItemUnpublished", + "CollectionItemUnpublishedPayload", + "CollectionItemUnpublishedPayloadFieldData", "CollectionItemWithIdInput", "CollectionItemWithIdInputFieldData", "CollectionList", "CollectionListArrayItem", + "Comment", + "CommentPayload", + "CommentPayloadAuthor", + "CommentPayloadMentionedUsersItem", + "CommentReply", + "CommentReplyAuthor", + "CommentReplyList", + "CommentReplyListPagination", + "CommentReplyMentionedUsersItem", + "CommentThread", + "CommentThreadAuthor", + "CommentThreadList", + "CommentThreadListPagination", + "CommentThreadMentionedUsersItem", "Component", "ComponentDom", "ComponentDomWriteNodesItem", @@ -255,21 +382,28 @@ "ComponentPropertyType", "ComponentsUpdateContentResponse", "ComponentsUpdatePropertiesResponse", + "Conflict", "ConflictError", - "ConflictErrorBody", "CustomCodeBlock", "CustomCodeBlockType", "CustomCodeHostedResponse", "CustomCodeInlineResponse", + "CustomRole", + "CustomRoleAuditLogItem", + "CustomRoleAuditLogItemEventSubType", "Dom", "Domain", "Domains", - "DuplicateUserEmail", + "EcommInventoryChangedPayload", "EcommerceSettings", "Error", "ErrorCode", "Field", + "FieldCreate", "FieldType", + "FieldValidations", + "FieldValidationsAdditionalProperties", + "FieldValidationsAdditionalPropertiesAdditionalProperties", "ForbiddenError", "ForbiddenErrorBody", "Form", @@ -280,6 +414,10 @@ "FormResponseSettings", "FormSubmission", "FormSubmissionList", + "FormSubmissionTrigger", + "FormSubmissionTriggerPayload", + "FormSubmissionTriggerPayloadSchemaItem", + "FormSubmissionTriggerPayloadSchemaItemFieldType", "ImageNode", "ImageNodeImage", "InternalServerError", @@ -288,21 +426,34 @@ "InventoryItem", "InventoryItemInventoryType", "InventoryUpdateRequestInventoryType", + "ItemsListItemsLiveRequestLastPublished", + "ItemsListItemsRequestLastPublished", "ListCustomCodeBlocks", "Locale", "Locales", + "Metadata", + "MetadataOptionsItem", + "NewOrder", "NoDomains", "Node", "Node_ComponentInstance", "Node_Image", + "Node_SearchButton", + "Node_Select", + "Node_SubmitButton", "Node_Text", + "Node_TextInput", "NotEnterprisePlanSite", "NotEnterprisePlanWorkspace", "NotFoundError", + "OptionField", "Order", "OrderAddress", "OrderAddressJapanType", "OrderAddressType", + "OrderBillingAddress", + "OrderBillingAddressJapanType", + "OrderBillingAddressType", "OrderCustomerInfo", "OrderDisputeLastStatus", "OrderDownloadFilesItem", @@ -313,6 +464,9 @@ "OrderPurchasedItemVariantImage", "OrderPurchasedItemVariantImageFile", "OrderPurchasedItemVariantImageFileVariantsItem", + "OrderShippingAddress", + "OrderShippingAddressJapanType", + "OrderShippingAddressType", "OrderStatus", "OrderTotals", "OrderTotalsExtrasItem", @@ -320,11 +474,21 @@ "OrdersListRequestStatus", "OrdersRefundRequestReason", "Page", + "PageCreatedWebhook", + "PageCreatedWebhookPayload", + "PageDeletedWebhook", + "PageDeletedWebhookPayload", "PageDomWriteNodesItem", "PageList", + "PageMetadataUpdatedWebhook", + "PageMetadataUpdatedWebhookPayload", + "PageMetadataWriteOpenGraph", + "PageMetadataWriteSeo", "PageOpenGraph", "PageSeo", "Pagination", + "Payload", + "PayloadFieldData", "PaypalDetails", "Product", "ProductAndSkUs", @@ -332,15 +496,32 @@ "ProductFieldData", "ProductFieldDataEcProductType", "ProductFieldDataTaxCategory", + "ProductSkuCreateProduct", + "ProductSkuCreateSku", "ProductsCreateSkuResponse", "PublishStatus", "Redirect", "Redirects", + "ReferenceField", + "ReferenceFieldMetadata", + "ReferenceFieldType", "RegisteredScriptList", + "Robots", + "RobotsRulesItem", "ScriptApply", "ScriptApplyList", "ScriptApplyLocation", "Scripts", + "SearchButtonNode", + "SearchButtonNodeWrite", + "Select", + "SelectNode", + "SelectNodeChoicesItem", + "SelectNodeWriteChoicesItem", + "SettingChange", + "SettingChangeAuditLogItem", + "SingleLocaleCreatedPayload", + "SingleLocaleCreatedPayloadFieldData", "Site", "SiteActivityLogItem", "SiteActivityLogItemEvent", @@ -348,9 +529,14 @@ "SiteActivityLogItemUser", "SiteActivityLogResponse", "SiteDataCollectionType", + "SiteMembership", + "SiteMembershipAuditLogItem", + "SiteMembershipAuditLogItemEventSubType", "SitePlan", "SitePlanId", "SitePlanName", + "SitePublish", + "SitePublishPayload", "Sites", "SitesPublishResponse", "Sku", @@ -365,11 +551,17 @@ "SkuPropertyList", "SkuPropertyListEnumItem", "SkuValueList", + "StaticField", + "StaticFieldType", "StripeCard", "StripeCardBrand", "StripeCardExpires", "StripeDetails", + "SubmitButtonNode", + "SubmitButtonNodeWrite", "Text", + "TextInputNode", + "TextInputNodeWrite", "TextNode", "TextNodeText", "TextNodeWrite", @@ -377,24 +569,46 @@ "TriggerType", "UnauthorizedError", "UpdateStaticContentResponse", - "User", - "UserAccessGroupsItem", - "UserAccessGroupsItemType", - "UserData", - "UserDataData", - "UserLimitReached", - "UserList", - "UserStatus", - "UsersListRequestSort", - "UsersNotEnabled", - "UsersUpdateRequestData", + "UpdatedOrder", + "UserAccess", + "UserAccessAuditLogItem", + "UserAccessAuditLogItemEventSubType", "Webflow", "WebflowEnvironment", "Webhook", "WebhookFilter", "WebhookList", + "WorkspaceAuditLogItem", + "WorkspaceAuditLogItemActor", + "WorkspaceAuditLogItemPayloadSettingChangeMethod", + "WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess", + "WorkspaceAuditLogItemPayloadSiteMembershipMethod", + "WorkspaceAuditLogItemPayloadSiteMembershipSite", + "WorkspaceAuditLogItemPayloadSiteMembershipTargetUser", + "WorkspaceAuditLogItemPayloadSiteMembershipUserType", + "WorkspaceAuditLogItemPayloadUserAccessMethod", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType", + "WorkspaceAuditLogItemWorkspace", + "WorkspaceAuditLogItem_CustomRole", + "WorkspaceAuditLogItem_SiteMembership", + "WorkspaceAuditLogItem_UserAccess", + "WorkspaceAuditLogItem_WorkspaceInvitation", + "WorkspaceAuditLogItem_WorkspaceMembership", + "WorkspaceAuditLogItem_WorkspaceSetting", + "WorkspaceAuditLogResponse", + "WorkspaceInvitation", + "WorkspaceInvitationAuditLogItem", + "WorkspaceInvitationAuditLogItemEventSubType", + "WorkspaceMembership", + "WorkspaceMembershipAuditLogItem", + "WorkspaceMembershipAuditLogItemEventSubType", "__version__", - "access_groups", "assets", "collections", "components", @@ -407,6 +621,6 @@ "scripts", "sites", "token", - "users", "webhooks", + "workspaces", ] diff --git a/src/webflow/client.py b/src/webflow/client.py index 90c233d..6f76267 100644 --- a/src/webflow/client.py +++ b/src/webflow/client.py @@ -1,7 +1,7 @@ # This file was auto-generated by Fern from our API Definition. -import typing from .environment import WebflowEnvironment +import typing import httpx from .core.client_wrapper import SyncClientWrapper from .resources.token.client import TokenClient @@ -13,12 +13,11 @@ from .resources.assets.client import AssetsClient from .resources.webhooks.client import WebhooksClient from .resources.forms.client import FormsClient -from .resources.users.client import UsersClient -from .resources.access_groups.client import AccessGroupsClient from .resources.products.client import ProductsClient from .resources.orders.client import OrdersClient from .resources.inventory.client import InventoryClient from .resources.ecommerce.client import EcommerceClient +from .resources.workspaces.client import WorkspacesClient from .core.client_wrapper import AsyncClientWrapper from .resources.token.client import AsyncTokenClient from .resources.sites.client import AsyncSitesClient @@ -29,12 +28,11 @@ from .resources.assets.client import AsyncAssetsClient from .resources.webhooks.client import AsyncWebhooksClient from .resources.forms.client import AsyncFormsClient -from .resources.users.client import AsyncUsersClient -from .resources.access_groups.client import AsyncAccessGroupsClient from .resources.products.client import AsyncProductsClient from .resources.orders.client import AsyncOrdersClient from .resources.inventory.client import AsyncInventoryClient from .resources.ecommerce.client import AsyncEcommerceClient +from .resources.workspaces.client import AsyncWorkspacesClient class Webflow: @@ -43,19 +41,16 @@ class Webflow: Parameters ---------- - base_url : typing.Optional[str] - The base url to use for requests from the client. - environment : WebflowEnvironment The environment to use for requests from the client. from .environment import WebflowEnvironment - Defaults to WebflowEnvironment.DEFAULT + Defaults to WebflowEnvironment.DATA_API - access_token : typing.Union[str, typing.Callable[[], str]] + access_token : typing.Optional[typing.Union[str, typing.Callable[[], str]]] timeout : typing.Optional[float] The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced. @@ -77,16 +72,15 @@ class Webflow: def __init__( self, *, - base_url: typing.Optional[str] = None, - environment: WebflowEnvironment = WebflowEnvironment.DEFAULT, - access_token: typing.Union[str, typing.Callable[[], str]], + environment: WebflowEnvironment = WebflowEnvironment.DATA_API, + access_token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, timeout: typing.Optional[float] = None, follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.Client] = None, ): _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None self._client_wrapper = SyncClientWrapper( - base_url=_get_base_url(base_url=base_url, environment=environment), + environment=environment, access_token=access_token, httpx_client=httpx_client if httpx_client is not None @@ -104,12 +98,11 @@ def __init__( self.assets = AssetsClient(client_wrapper=self._client_wrapper) self.webhooks = WebhooksClient(client_wrapper=self._client_wrapper) self.forms = FormsClient(client_wrapper=self._client_wrapper) - self.users = UsersClient(client_wrapper=self._client_wrapper) - self.access_groups = AccessGroupsClient(client_wrapper=self._client_wrapper) self.products = ProductsClient(client_wrapper=self._client_wrapper) self.orders = OrdersClient(client_wrapper=self._client_wrapper) self.inventory = InventoryClient(client_wrapper=self._client_wrapper) self.ecommerce = EcommerceClient(client_wrapper=self._client_wrapper) + self.workspaces = WorkspacesClient(client_wrapper=self._client_wrapper) class AsyncWebflow: @@ -118,19 +111,16 @@ class AsyncWebflow: Parameters ---------- - base_url : typing.Optional[str] - The base url to use for requests from the client. - environment : WebflowEnvironment The environment to use for requests from the client. from .environment import WebflowEnvironment - Defaults to WebflowEnvironment.DEFAULT + Defaults to WebflowEnvironment.DATA_API - access_token : typing.Union[str, typing.Callable[[], str]] + access_token : typing.Optional[typing.Union[str, typing.Callable[[], str]]] timeout : typing.Optional[float] The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced. @@ -152,16 +142,15 @@ class AsyncWebflow: def __init__( self, *, - base_url: typing.Optional[str] = None, - environment: WebflowEnvironment = WebflowEnvironment.DEFAULT, - access_token: typing.Union[str, typing.Callable[[], str]], + environment: WebflowEnvironment = WebflowEnvironment.DATA_API, + access_token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, timeout: typing.Optional[float] = None, follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.AsyncClient] = None, ): _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None self._client_wrapper = AsyncClientWrapper( - base_url=_get_base_url(base_url=base_url, environment=environment), + environment=environment, access_token=access_token, httpx_client=httpx_client if httpx_client is not None @@ -179,18 +168,8 @@ def __init__( self.assets = AsyncAssetsClient(client_wrapper=self._client_wrapper) self.webhooks = AsyncWebhooksClient(client_wrapper=self._client_wrapper) self.forms = AsyncFormsClient(client_wrapper=self._client_wrapper) - self.users = AsyncUsersClient(client_wrapper=self._client_wrapper) - self.access_groups = AsyncAccessGroupsClient(client_wrapper=self._client_wrapper) self.products = AsyncProductsClient(client_wrapper=self._client_wrapper) self.orders = AsyncOrdersClient(client_wrapper=self._client_wrapper) self.inventory = AsyncInventoryClient(client_wrapper=self._client_wrapper) self.ecommerce = AsyncEcommerceClient(client_wrapper=self._client_wrapper) - - -def _get_base_url(*, base_url: typing.Optional[str] = None, environment: WebflowEnvironment) -> str: - if base_url is not None: - return base_url - elif environment is not None: - return environment.value - else: - raise Exception("Please pass in either base_url or environment to construct the client") + self.workspaces = AsyncWorkspacesClient(client_wrapper=self._client_wrapper) diff --git a/src/webflow/core/client_wrapper.py b/src/webflow/core/client_wrapper.py index a04487e..3849c42 100644 --- a/src/webflow/core/client_wrapper.py +++ b/src/webflow/core/client_wrapper.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing +from ..environment import WebflowEnvironment import httpx from .http_client import HttpClient from .http_client import AsyncHttpClient @@ -10,31 +11,33 @@ class BaseClientWrapper: def __init__( self, *, - access_token: typing.Union[str, typing.Callable[[], str]], - base_url: str, + access_token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + environment: WebflowEnvironment, timeout: typing.Optional[float] = None, ): self._access_token = access_token - self._base_url = base_url + self._environment = environment self._timeout = timeout def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { "X-Fern-Language": "Python", "X-Fern-SDK-Name": "webflow", - "X-Fern-SDK-Version": "2.0.0b2", + "X-Fern-SDK-Version": "1.2.1", } - headers["Authorization"] = f"Bearer {self._get_access_token()}" + access_token = self._get_access_token() + if access_token is not None: + headers["Authorization"] = f"Bearer {access_token}" return headers - def _get_access_token(self) -> str: - if isinstance(self._access_token, str): + def _get_access_token(self) -> typing.Optional[str]: + if isinstance(self._access_token, str) or self._access_token is None: return self._access_token else: return self._access_token() - def get_base_url(self) -> str: - return self._base_url + def get_environment(self) -> WebflowEnvironment: + return self._environment def get_timeout(self) -> typing.Optional[float]: return self._timeout @@ -44,17 +47,14 @@ class SyncClientWrapper(BaseClientWrapper): def __init__( self, *, - access_token: typing.Union[str, typing.Callable[[], str]], - base_url: str, + access_token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + environment: WebflowEnvironment, timeout: typing.Optional[float] = None, httpx_client: httpx.Client, ): - super().__init__(access_token=access_token, base_url=base_url, timeout=timeout) + super().__init__(access_token=access_token, environment=environment, timeout=timeout) self.httpx_client = HttpClient( - httpx_client=httpx_client, - base_headers=self.get_headers, - base_timeout=self.get_timeout, - base_url=self.get_base_url, + httpx_client=httpx_client, base_headers=self.get_headers, base_timeout=self.get_timeout ) @@ -62,15 +62,12 @@ class AsyncClientWrapper(BaseClientWrapper): def __init__( self, *, - access_token: typing.Union[str, typing.Callable[[], str]], - base_url: str, + access_token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + environment: WebflowEnvironment, timeout: typing.Optional[float] = None, httpx_client: httpx.AsyncClient, ): - super().__init__(access_token=access_token, base_url=base_url, timeout=timeout) + super().__init__(access_token=access_token, environment=environment, timeout=timeout) self.httpx_client = AsyncHttpClient( - httpx_client=httpx_client, - base_headers=self.get_headers, - base_timeout=self.get_timeout, - base_url=self.get_base_url, + httpx_client=httpx_client, base_headers=self.get_headers, base_timeout=self.get_timeout ) diff --git a/src/webflow/environment.py b/src/webflow/environment.py index ed0e03d..07a5c81 100644 --- a/src/webflow/environment.py +++ b/src/webflow/environment.py @@ -1,7 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -import enum +from __future__ import annotations -class WebflowEnvironment(enum.Enum): - DEFAULT = "https://api.webflow.com/v2" +class WebflowEnvironment: + DATA_API: WebflowEnvironment + + def __init__(self, *, base: str, data_api: str, content_delivery_api: str): + self.base = base + self.data_api = data_api + self.content_delivery_api = content_delivery_api + + +WebflowEnvironment.DATA_API = WebflowEnvironment( + base="https://api.webflow.com/v2", + data_api="https://api.webflow.com/v2", + content_delivery_api="https://api-cdn.webflow.com/v2", +) diff --git a/src/webflow/resources/__init__.py b/src/webflow/resources/__init__.py index 9122eee..eb58716 100644 --- a/src/webflow/resources/__init__.py +++ b/src/webflow/resources/__init__.py @@ -1,7 +1,6 @@ # This file was auto-generated by Fern from our API Definition. from . import ( - access_groups, assets, collections, components, @@ -14,39 +13,38 @@ scripts, sites, token, - users, webhooks, + workspaces, ) -from .access_groups import AccessGroupsListRequestSort from .components import ( ComponentDomWriteNodesItem, ComponentPropertiesWritePropertiesItem, ComponentsUpdateContentResponse, ComponentsUpdatePropertiesResponse, ) -from .inventory import InventoryUpdateRequestInventoryType +from .inventory import EcommInventoryChangedPayload, InventoryUpdateRequestInventoryType from .orders import OrdersListRequestStatus, OrdersRefundRequestReason -from .pages import PageDomWriteNodesItem, UpdateStaticContentResponse -from .products import ProductsCreateSkuResponse +from .pages import PageDomWriteNodesItem, PageMetadataWriteOpenGraph, PageMetadataWriteSeo, UpdateStaticContentResponse +from .products import ProductSkuCreateProduct, ProductSkuCreateSku, ProductsCreateSkuResponse from .sites import SitesPublishResponse -from .users import UsersListRequestSort, UsersUpdateRequestData __all__ = [ - "AccessGroupsListRequestSort", "ComponentDomWriteNodesItem", "ComponentPropertiesWritePropertiesItem", "ComponentsUpdateContentResponse", "ComponentsUpdatePropertiesResponse", + "EcommInventoryChangedPayload", "InventoryUpdateRequestInventoryType", "OrdersListRequestStatus", "OrdersRefundRequestReason", "PageDomWriteNodesItem", + "PageMetadataWriteOpenGraph", + "PageMetadataWriteSeo", + "ProductSkuCreateProduct", + "ProductSkuCreateSku", "ProductsCreateSkuResponse", "SitesPublishResponse", "UpdateStaticContentResponse", - "UsersListRequestSort", - "UsersUpdateRequestData", - "access_groups", "assets", "collections", "components", @@ -59,6 +57,6 @@ "scripts", "sites", "token", - "users", "webhooks", + "workspaces", ] diff --git a/src/webflow/resources/access_groups/__init__.py b/src/webflow/resources/access_groups/__init__.py deleted file mode 100644 index b46e2ae..0000000 --- a/src/webflow/resources/access_groups/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .types import AccessGroupsListRequestSort - -__all__ = ["AccessGroupsListRequestSort"] diff --git a/src/webflow/resources/access_groups/types/__init__.py b/src/webflow/resources/access_groups/types/__init__.py deleted file mode 100644 index e721e22..0000000 --- a/src/webflow/resources/access_groups/types/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .access_groups_list_request_sort import AccessGroupsListRequestSort - -__all__ = ["AccessGroupsListRequestSort"] diff --git a/src/webflow/resources/access_groups/types/access_groups_list_request_sort.py b/src/webflow/resources/access_groups/types/access_groups_list_request_sort.py deleted file mode 100644 index 074583a..0000000 --- a/src/webflow/resources/access_groups/types/access_groups_list_request_sort.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -AccessGroupsListRequestSort = typing.Union[typing.Literal["CreatedOn", "-CreatedOn"], typing.Any] diff --git a/src/webflow/resources/assets/client.py b/src/webflow/resources/assets/client.py index 61e141a..d2723f9 100644 --- a/src/webflow/resources/assets/client.py +++ b/src/webflow/resources/assets/client.py @@ -28,9 +28,16 @@ class AssetsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper - def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Assets: + def list( + self, + site_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> Assets: """ - List assets for a given site + List of assets uploaded to a site Required scope | `assets:read` @@ -39,6 +46,12 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] site_id : str Unique identifier for a Site + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -56,11 +69,18 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] ) client.assets.list( site_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, method="GET", + params={ + "offset": offset, + "limit": limit, + }, request_options=request_options, ) try: @@ -137,15 +157,18 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> AssetUpload: """ - Create a new asset entry. + The first step in uploading an asset to a site. This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. - You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) - request to the `uploadUrl` with the `uploadDetails` object as your header information in the request. - Required scope | `assets:write` + Use these properties in the header of a [POST request to Amazson s3](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) to complete the upload. + + + To learn more about how to upload assets to Webflow, see our [assets guide](/data/docs/working-with-assets). + + Required scope | `assets:write` Parameters ---------- @@ -184,6 +207,7 @@ def create( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "fileName": file_name, @@ -262,7 +286,7 @@ def create( def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Asset: """ - Get an Asset + Get details about an asset Required scope | `assets:read` @@ -292,6 +316,7 @@ def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -390,6 +415,7 @@ def delete(self, asset_id: str, *, request_options: typing.Optional[RequestOptio """ _response = self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -460,7 +486,7 @@ def update( request_options: typing.Optional[RequestOptions] = None, ) -> Asset: """ - Update an Asset + Update details of an Asset. Required scope | `assets:write` @@ -496,6 +522,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "localeId": locale_id, @@ -603,6 +630,7 @@ def list_folders(self, site_id: str, *, request_options: typing.Optional[Request """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -716,6 +744,7 @@ def create_folder( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "displayName": display_name, @@ -825,6 +854,7 @@ def get_folder( """ _response = self._client_wrapper.httpx_client.request( f"asset_folders/{jsonable_encoder(asset_folder_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -897,9 +927,16 @@ class AsyncAssetsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper - async def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Assets: + async def list( + self, + site_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> Assets: """ - List assets for a given site + List of assets uploaded to a site Required scope | `assets:read` @@ -908,6 +945,12 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp site_id : str Unique identifier for a Site + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -930,6 +973,8 @@ async def list(self, site_id: str, *, request_options: typing.Optional[RequestOp async def main() -> None: await client.assets.list( site_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) @@ -937,7 +982,12 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, method="GET", + params={ + "offset": offset, + "limit": limit, + }, request_options=request_options, ) try: @@ -1014,15 +1064,18 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> AssetUpload: """ - Create a new asset entry. + The first step in uploading an asset to a site. This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. - You can use these two properties to [upload the file to Amazon s3 by making a POST](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) - request to the `uploadUrl` with the `uploadDetails` object as your header information in the request. - Required scope | `assets:write` + Use these properties in the header of a [POST request to Amazson s3](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) to complete the upload. + + + To learn more about how to upload assets to Webflow, see our [assets guide](/data/docs/working-with-assets). + + Required scope | `assets:write` Parameters ---------- @@ -1069,6 +1122,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "fileName": file_name, @@ -1147,7 +1201,7 @@ async def main() -> None: async def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Asset: """ - Get an Asset + Get details about an asset Required scope | `assets:read` @@ -1185,6 +1239,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1291,6 +1346,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -1361,7 +1417,7 @@ async def update( request_options: typing.Optional[RequestOptions] = None, ) -> Asset: """ - Update an Asset + Update details of an Asset. Required scope | `assets:write` @@ -1405,6 +1461,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "localeId": locale_id, @@ -1522,6 +1579,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1643,6 +1701,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "displayName": display_name, @@ -1760,6 +1819,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"asset_folders/{jsonable_encoder(asset_folder_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) diff --git a/src/webflow/resources/collections/__init__.py b/src/webflow/resources/collections/__init__.py index cb6aaf8..3796806 100644 --- a/src/webflow/resources/collections/__init__.py +++ b/src/webflow/resources/collections/__init__.py @@ -3,16 +3,20 @@ from .resources import ( CreateBulkCollectionItemRequestBodyFieldData, CreateBulkCollectionItemRequestBodyFieldDataItem, - FieldCreateType, - ItemsCreateItemLiveRequest, - ItemsCreateItemRequest, + ItemIDs, + ItemIDsWithLocales, + ItemsCreateItemLiveRequestBody, + ItemsCreateItemRequestBody, ItemsDeleteItemsLiveRequestItemsItem, ItemsDeleteItemsRequestItemsItem, ItemsListItemsLiveRequestSortBy, ItemsListItemsLiveRequestSortOrder, ItemsListItemsRequestSortBy, ItemsListItemsRequestSortOrder, + ItemsPublishItemRequest, + ItemsPublishItemRequestItemsItemsItem, ItemsPublishItemResponse, + ItemsUpdateItemsResponse, MultipleItems, MultipleLiveItems, SingleCmsItem, @@ -23,16 +27,20 @@ __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", "CreateBulkCollectionItemRequestBodyFieldDataItem", - "FieldCreateType", - "ItemsCreateItemLiveRequest", - "ItemsCreateItemRequest", + "ItemIDs", + "ItemIDsWithLocales", + "ItemsCreateItemLiveRequestBody", + "ItemsCreateItemRequestBody", "ItemsDeleteItemsLiveRequestItemsItem", "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemRequest", + "ItemsPublishItemRequestItemsItemsItem", "ItemsPublishItemResponse", + "ItemsUpdateItemsResponse", "MultipleItems", "MultipleLiveItems", "SingleCmsItem", diff --git a/src/webflow/resources/collections/client.py b/src/webflow/resources/collections/client.py index 1e44aae..61495ae 100644 --- a/src/webflow/resources/collections/client.py +++ b/src/webflow/resources/collections/client.py @@ -16,7 +16,10 @@ from ...errors.internal_server_error import InternalServerError from json.decoder import JSONDecodeError from ...core.api_error import ApiError +from ...types.field_create import FieldCreate from ...types.collection import Collection +from ...core.serialization import convert_and_respect_annotation_metadata +from ...errors.conflict_error import ConflictError from ...core.client_wrapper import AsyncClientWrapper from .resources.fields.client import AsyncFieldsClient from .resources.items.client import AsyncItemsClient @@ -63,6 +66,7 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -137,10 +141,13 @@ def create( display_name: str, singular_name: str, slug: typing.Optional[str] = OMIT, + fields: typing.Optional[typing.Sequence[FieldCreate]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Collection: """ - Create a Collection for a site. + Create a Collection for a site with collection fields. + + Each collection includes the required _name_ and _slug_ fields, which are generated automatically. You can update the `displayName` of these fields, but the slug for them cannot be changed. Fields slugs are automatically converted to lowercase. Spaces in slugs are replaced with hyphens. Required scope | `cms:write` @@ -158,6 +165,9 @@ def create( slug : typing.Optional[str] Part of a URL that identifier + fields : typing.Optional[typing.Sequence[FieldCreate]] + An array of custom fields to add to the collection + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -168,7 +178,7 @@ def create( Examples -------- - from webflow import Webflow + from webflow import ReferenceField, ReferenceFieldMetadata, StaticField, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -178,15 +188,42 @@ def create( display_name="Blog Posts", singular_name="Blog Post", slug="posts", + fields=[ + StaticField( + is_required=True, + type="PlainText", + display_name="Title", + help_text="The title of the blog post", + ), + StaticField( + is_required=True, + type="RichText", + display_name="Content", + help_text="The content of the blog post", + ), + ReferenceField( + is_required=True, + type="Reference", + display_name="Author", + help_text="The author of the blog post", + metadata=ReferenceFieldMetadata( + collection_id="23cc2d952d4e4631ffd4345d2743db4e", + ), + ), + ], ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "displayName": display_name, "singularName": singular_name, "slug": slug, + "fields": convert_and_respect_annotation_metadata( + object_=fields, annotation=typing.Sequence[FieldCreate], direction="write" + ), }, headers={ "content-type": "application/json", @@ -233,6 +270,16 @@ def create( ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -290,6 +337,7 @@ def get(self, collection_id: str, *, request_options: typing.Optional[RequestOpt """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -388,6 +436,7 @@ def delete(self, collection_id: str, *, request_options: typing.Optional[Request """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -496,6 +545,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -570,10 +620,13 @@ async def create( display_name: str, singular_name: str, slug: typing.Optional[str] = OMIT, + fields: typing.Optional[typing.Sequence[FieldCreate]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Collection: """ - Create a Collection for a site. + Create a Collection for a site with collection fields. + + Each collection includes the required _name_ and _slug_ fields, which are generated automatically. You can update the `displayName` of these fields, but the slug for them cannot be changed. Fields slugs are automatically converted to lowercase. Spaces in slugs are replaced with hyphens. Required scope | `cms:write` @@ -591,6 +644,9 @@ async def create( slug : typing.Optional[str] Part of a URL that identifier + fields : typing.Optional[typing.Sequence[FieldCreate]] + An array of custom fields to add to the collection + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -603,7 +659,12 @@ async def create( -------- import asyncio - from webflow import AsyncWebflow + from webflow import ( + AsyncWebflow, + ReferenceField, + ReferenceFieldMetadata, + StaticField, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -616,6 +677,29 @@ async def main() -> None: display_name="Blog Posts", singular_name="Blog Post", slug="posts", + fields=[ + StaticField( + is_required=True, + type="PlainText", + display_name="Title", + help_text="The title of the blog post", + ), + StaticField( + is_required=True, + type="RichText", + display_name="Content", + help_text="The content of the blog post", + ), + ReferenceField( + is_required=True, + type="Reference", + display_name="Author", + help_text="The author of the blog post", + metadata=ReferenceFieldMetadata( + collection_id="23cc2d952d4e4631ffd4345d2743db4e", + ), + ), + ], ) @@ -623,11 +707,15 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "displayName": display_name, "singularName": singular_name, "slug": slug, + "fields": convert_and_respect_annotation_metadata( + object_=fields, annotation=typing.Sequence[FieldCreate], direction="write" + ), }, headers={ "content-type": "application/json", @@ -674,6 +762,16 @@ async def main() -> None: ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -739,6 +837,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -845,6 +944,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) diff --git a/src/webflow/resources/collections/resources/__init__.py b/src/webflow/resources/collections/resources/__init__.py index f9325ee..4ad4d58 100644 --- a/src/webflow/resources/collections/resources/__init__.py +++ b/src/webflow/resources/collections/resources/__init__.py @@ -1,19 +1,23 @@ # This file was auto-generated by Fern from our API Definition. from . import fields, items -from .fields import FieldCreateType from .items import ( CreateBulkCollectionItemRequestBodyFieldData, CreateBulkCollectionItemRequestBodyFieldDataItem, - ItemsCreateItemLiveRequest, - ItemsCreateItemRequest, + ItemIDs, + ItemIDsWithLocales, + ItemsCreateItemLiveRequestBody, + ItemsCreateItemRequestBody, ItemsDeleteItemsLiveRequestItemsItem, ItemsDeleteItemsRequestItemsItem, ItemsListItemsLiveRequestSortBy, ItemsListItemsLiveRequestSortOrder, ItemsListItemsRequestSortBy, ItemsListItemsRequestSortOrder, + ItemsPublishItemRequest, + ItemsPublishItemRequestItemsItemsItem, ItemsPublishItemResponse, + ItemsUpdateItemsResponse, MultipleItems, MultipleLiveItems, SingleCmsItem, @@ -22,16 +26,20 @@ __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", "CreateBulkCollectionItemRequestBodyFieldDataItem", - "FieldCreateType", - "ItemsCreateItemLiveRequest", - "ItemsCreateItemRequest", + "ItemIDs", + "ItemIDsWithLocales", + "ItemsCreateItemLiveRequestBody", + "ItemsCreateItemRequestBody", "ItemsDeleteItemsLiveRequestItemsItem", "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemRequest", + "ItemsPublishItemRequestItemsItemsItem", "ItemsPublishItemResponse", + "ItemsUpdateItemsResponse", "MultipleItems", "MultipleLiveItems", "SingleCmsItem", diff --git a/src/webflow/resources/collections/resources/fields/__init__.py b/src/webflow/resources/collections/resources/fields/__init__.py index 5a5b167..f3ea265 100644 --- a/src/webflow/resources/collections/resources/fields/__init__.py +++ b/src/webflow/resources/collections/resources/fields/__init__.py @@ -1,5 +1,2 @@ # This file was auto-generated by Fern from our API Definition. -from .types import FieldCreateType - -__all__ = ["FieldCreateType"] diff --git a/src/webflow/resources/collections/resources/fields/client.py b/src/webflow/resources/collections/resources/fields/client.py index 40b66cf..c2b7ebc 100644 --- a/src/webflow/resources/collections/resources/fields/client.py +++ b/src/webflow/resources/collections/resources/fields/client.py @@ -2,19 +2,21 @@ import typing from .....core.client_wrapper import SyncClientWrapper -from .types.field_create_type import FieldCreateType +from .....types.field_create import FieldCreate from .....core.request_options import RequestOptions -from .....types.field import Field from .....core.jsonable_encoder import jsonable_encoder +from .....core.serialization import convert_and_respect_annotation_metadata from .....core.pydantic_utilities import parse_obj_as from .....errors.bad_request_error import BadRequestError from .....errors.unauthorized_error import UnauthorizedError from .....types.error import Error from .....errors.not_found_error import NotFoundError +from .....errors.conflict_error import ConflictError from .....errors.too_many_requests_error import TooManyRequestsError from .....errors.internal_server_error import InternalServerError from json.decoder import JSONDecodeError from .....core.api_error import ApiError +from .....types.field import Field from .....core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters @@ -26,24 +28,14 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper def create( - self, - collection_id: str, - *, - type: FieldCreateType, - display_name: str, - is_required: typing.Optional[bool] = OMIT, - help_text: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Field: + self, collection_id: str, *, request: FieldCreate, request_options: typing.Optional[RequestOptions] = None + ) -> FieldCreate: """ Create a custom field in a collection. - Slugs must be all lowercase letters without spaces. - If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will - convert the slug to lowercase and replace spaces with "-." + Field validation is currently not available through the API. - Only some field types can be created through the API. - This endpoint does not currently support bulk creation. + Bulk creation of fields is not supported with this endpoint. To add multiple fields at once, include them when you [create the collection.](/data/v2.0.0/reference/cms/collections/create) Required scope | `cms:write` @@ -52,62 +44,49 @@ def create( collection_id : str Unique identifier for a Collection - type : FieldCreateType - Choose these appropriate field type for your collection data - - display_name : str - The name of a field - - is_required : typing.Optional[bool] - define whether a field is required in a collection - - help_text : typing.Optional[str] - Additional text to help anyone filling out this field + request : FieldCreate request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - Field + FieldCreate Request was successful Examples -------- - from webflow import Webflow + from webflow import StaticField, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.fields.create( collection_id="580e63fc8c9a982ac9b8b745", - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", + request=StaticField( + id="562ac0395358780a1f5e6fbc", + is_editable=True, + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", + ), ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields", + base_url=self._client_wrapper.get_environment().base, method="POST", - json={ - "isRequired": is_required, - "type": type, - "displayName": display_name, - "helpText": help_text, - }, - headers={ - "content-type": "application/json", - }, + json=convert_and_respect_annotation_metadata(object_=request, annotation=FieldCreate, direction="write"), request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: return typing.cast( - Field, + FieldCreate, parse_obj_as( - type_=Field, # type: ignore + type_=FieldCreate, # type: ignore object_=_response.json(), ), ) @@ -141,6 +120,16 @@ def create( ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -203,6 +192,7 @@ def delete( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -321,6 +311,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "isRequired": is_required, @@ -403,24 +394,14 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper async def create( - self, - collection_id: str, - *, - type: FieldCreateType, - display_name: str, - is_required: typing.Optional[bool] = OMIT, - help_text: typing.Optional[str] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> Field: + self, collection_id: str, *, request: FieldCreate, request_options: typing.Optional[RequestOptions] = None + ) -> FieldCreate: """ Create a custom field in a collection. - Slugs must be all lowercase letters without spaces. - If you pass a string with uppercase letters and/or spaces to the "Slug" property, Webflow will - convert the slug to lowercase and replace spaces with "-." + Field validation is currently not available through the API. - Only some field types can be created through the API. - This endpoint does not currently support bulk creation. + Bulk creation of fields is not supported with this endpoint. To add multiple fields at once, include them when you [create the collection.](/data/v2.0.0/reference/cms/collections/create) Required scope | `cms:write` @@ -429,31 +410,21 @@ async def create( collection_id : str Unique identifier for a Collection - type : FieldCreateType - Choose these appropriate field type for your collection data - - display_name : str - The name of a field - - is_required : typing.Optional[bool] - define whether a field is required in a collection - - help_text : typing.Optional[str] - Additional text to help anyone filling out this field + request : FieldCreate request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - Field + FieldCreate Request was successful Examples -------- import asyncio - from webflow import AsyncWebflow + from webflow import AsyncWebflow, StaticField client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -463,10 +434,14 @@ async def create( async def main() -> None: await client.collections.fields.create( collection_id="580e63fc8c9a982ac9b8b745", - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", + request=StaticField( + id="562ac0395358780a1f5e6fbc", + is_editable=True, + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", + ), ) @@ -474,25 +449,18 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields", + base_url=self._client_wrapper.get_environment().base, method="POST", - json={ - "isRequired": is_required, - "type": type, - "displayName": display_name, - "helpText": help_text, - }, - headers={ - "content-type": "application/json", - }, + json=convert_and_respect_annotation_metadata(object_=request, annotation=FieldCreate, direction="write"), request_options=request_options, omit=OMIT, ) try: if 200 <= _response.status_code < 300: return typing.cast( - Field, + FieldCreate, parse_obj_as( - type_=Field, # type: ignore + type_=FieldCreate, # type: ignore object_=_response.json(), ), ) @@ -526,6 +494,16 @@ async def main() -> None: ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -596,6 +574,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -722,6 +701,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "isRequired": is_required, diff --git a/src/webflow/resources/collections/resources/fields/types/__init__.py b/src/webflow/resources/collections/resources/fields/types/__init__.py deleted file mode 100644 index c17230e..0000000 --- a/src/webflow/resources/collections/resources/fields/types/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .field_create_type import FieldCreateType - -__all__ = ["FieldCreateType"] diff --git a/src/webflow/resources/collections/resources/items/__init__.py b/src/webflow/resources/collections/resources/items/__init__.py index fbccd1b..7dce40c 100644 --- a/src/webflow/resources/collections/resources/items/__init__.py +++ b/src/webflow/resources/collections/resources/items/__init__.py @@ -3,15 +3,20 @@ from .types import ( CreateBulkCollectionItemRequestBodyFieldData, CreateBulkCollectionItemRequestBodyFieldDataItem, - ItemsCreateItemLiveRequest, - ItemsCreateItemRequest, + ItemIDs, + ItemIDsWithLocales, + ItemsCreateItemLiveRequestBody, + ItemsCreateItemRequestBody, ItemsDeleteItemsLiveRequestItemsItem, ItemsDeleteItemsRequestItemsItem, ItemsListItemsLiveRequestSortBy, ItemsListItemsLiveRequestSortOrder, ItemsListItemsRequestSortBy, ItemsListItemsRequestSortOrder, + ItemsPublishItemRequest, + ItemsPublishItemRequestItemsItemsItem, ItemsPublishItemResponse, + ItemsUpdateItemsResponse, MultipleItems, MultipleLiveItems, SingleCmsItem, @@ -20,15 +25,20 @@ __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", "CreateBulkCollectionItemRequestBodyFieldDataItem", - "ItemsCreateItemLiveRequest", - "ItemsCreateItemRequest", + "ItemIDs", + "ItemIDsWithLocales", + "ItemsCreateItemLiveRequestBody", + "ItemsCreateItemRequestBody", "ItemsDeleteItemsLiveRequestItemsItem", "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemRequest", + "ItemsPublishItemRequestItemsItemsItem", "ItemsPublishItemResponse", + "ItemsUpdateItemsResponse", "MultipleItems", "MultipleLiveItems", "SingleCmsItem", diff --git a/src/webflow/resources/collections/resources/items/client.py b/src/webflow/resources/collections/resources/items/client.py index 47f8f90..0e04307 100644 --- a/src/webflow/resources/collections/resources/items/client.py +++ b/src/webflow/resources/collections/resources/items/client.py @@ -2,11 +2,13 @@ import typing from .....core.client_wrapper import SyncClientWrapper +from .....types.items_list_items_request_last_published import ItemsListItemsRequestLastPublished from .types.items_list_items_request_sort_by import ItemsListItemsRequestSortBy from .types.items_list_items_request_sort_order import ItemsListItemsRequestSortOrder from .....core.request_options import RequestOptions from .....types.collection_item_list import CollectionItemList from .....core.jsonable_encoder import jsonable_encoder +from .....core.serialization import convert_and_respect_annotation_metadata from .....core.pydantic_utilities import parse_obj_as from .....errors.bad_request_error import BadRequestError from .....errors.unauthorized_error import UnauthorizedError @@ -16,20 +18,22 @@ from .....errors.internal_server_error import InternalServerError from json.decoder import JSONDecodeError from .....core.api_error import ApiError -from .types.items_create_item_request import ItemsCreateItemRequest +from .types.items_create_item_request_body import ItemsCreateItemRequestBody from .....types.collection_item import CollectionItem -from .....core.serialization import convert_and_respect_annotation_metadata from .types.items_delete_items_request_items_item import ItemsDeleteItemsRequestItemsItem from .....errors.conflict_error import ConflictError from .....types.collection_item_with_id_input import CollectionItemWithIdInput +from .types.items_update_items_response import ItemsUpdateItemsResponse +from .....types.items_list_items_live_request_last_published import ItemsListItemsLiveRequestLastPublished from .types.items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy from .types.items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder -from .types.items_create_item_live_request import ItemsCreateItemLiveRequest +from .types.items_create_item_live_request_body import ItemsCreateItemLiveRequestBody from .types.items_delete_items_live_request_items_item import ItemsDeleteItemsLiveRequestItemsItem from .....types.collection_item_list_no_pagination import CollectionItemListNoPagination from .types.create_bulk_collection_item_request_body_field_data import CreateBulkCollectionItemRequestBodyFieldData from .....types.bulk_collection_item import BulkCollectionItem from .....types.collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData +from .types.items_publish_item_request import ItemsPublishItemRequest from .types.items_publish_item_response import ItemsPublishItemResponse from .....core.client_wrapper import AsyncClientWrapper @@ -46,10 +50,11 @@ def list_items( collection_id: str, *, cms_locale_id: typing.Optional[str] = None, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, name: typing.Optional[str] = None, slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsRequestLastPublished] = None, sort_by: typing.Optional[ItemsListItemsRequestSortBy] = None, sort_order: typing.Optional[ItemsListItemsRequestSortOrder] = None, request_options: typing.Optional[RequestOptions] = None, @@ -67,17 +72,20 @@ def list_items( cms_locale_id : typing.Optional[str] Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) name : typing.Optional[str] - The name of the item(s) + Filter by the exact name of the item(s) slug : typing.Optional[str] - The slug of the item + Filter by the exact slug of the item + + last_published : typing.Optional[ItemsListItemsRequestLastPublished] + Filter by the last published date of the item(s) sort_by : typing.Optional[ItemsListItemsRequestSortBy] Sort results by the provided value @@ -102,10 +110,18 @@ def list_items( ) client.collections.items.list_items( collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_id="cmsLocaleId", + offset=1, + limit=1, + name="name", + slug="slug", + sort_by="lastPublished", + sort_order="asc", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -113,6 +129,9 @@ def list_items( "limit": limit, "name": name, "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsRequestLastPublished, direction="write" + ), "sortBy": sort_by, "sortOrder": sort_order, }, @@ -186,14 +205,15 @@ def create_item( self, collection_id: str, *, - request: ItemsCreateItemRequest, + request: ItemsCreateItemRequestBody, + skip_invalid_files: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ Create Item(s) in a Collection. - To create items across multiple locales, please use [this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + To create items across multiple locales, please use [this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write` @@ -202,7 +222,10 @@ def create_item( collection_id : str Unique identifier for a Collection - request : ItemsCreateItemRequest + request : ItemsCreateItemRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -225,21 +248,26 @@ def create_item( ) client.collections.items.create_item( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, request=CollectionItemPostSingle( is_archived=False, is_draft=False, field_data=CollectionItemPostSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", + name="The Hitchhiker's Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", ), ), ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemRequest, direction="write" + object_=request, annotation=ItemsCreateItemRequestBody, direction="write" ), request_options=request_options, omit=OMIT, @@ -312,13 +340,13 @@ def delete_items( self, collection_id: str, *, - items: typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] = OMIT, + items: typing.Sequence[ItemsDeleteItemsRequestItemsItem], request_options: typing.Optional[RequestOptions] = None, ) -> None: """ Delete Items from a Collection. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be deleted only in the primary locale. + Items will only be deleted in the primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -327,7 +355,7 @@ def delete_items( collection_id : str Unique identifier for a Collection - items : typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] + items : typing.Sequence[ItemsDeleteItemsRequestItemsItem] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -339,16 +367,25 @@ def delete_items( Examples -------- from webflow import Webflow + from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsRequestItemsItem, + ) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.delete_items( collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="DELETE", json={ "items": convert_and_respect_annotation_metadata( @@ -433,13 +470,16 @@ def update_items( self, collection_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CollectionItem: + ) -> ItemsUpdateItemsResponse: """ - Update a single item or multiple items (up to 100) in a Collection. + Update a single item or multiple items in a Collection. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + The limit for this endpoint is 100 items. + + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -448,6 +488,9 @@ def update_items( collection_id : str Unique identifier for a Collection + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] request_options : typing.Optional[RequestOptions] @@ -455,7 +498,7 @@ def update_items( Returns ------- - CollectionItem + ItemsUpdateItemsResponse Request was successful Examples @@ -471,6 +514,7 @@ def update_items( ) client.collections.items.update_items( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, items=[ CollectionItemWithIdInput( id="66f6ed9576ddacf3149d5ea6", @@ -509,7 +553,11 @@ def update_items( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "items": convert_and_respect_annotation_metadata( object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" @@ -524,9 +572,9 @@ def update_items( try: if 200 <= _response.status_code < 300: return typing.cast( - CollectionItem, + ItemsUpdateItemsResponse, parse_obj_as( - type_=CollectionItem, # type: ignore + type_=ItemsUpdateItemsResponse, # type: ignore object_=_response.json(), ), ) @@ -590,16 +638,21 @@ def list_items_live( collection_id: str, *, cms_locale_id: typing.Optional[str] = None, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, name: typing.Optional[str] = None, slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsLiveRequestLastPublished] = None, sort_by: typing.Optional[ItemsListItemsLiveRequestSortBy] = None, sort_order: typing.Optional[ItemsListItemsLiveRequestSortOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemList: """ - List of all live Items within a Collection. + List all published items in a collection. + + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + Required scope | `CMS:read` @@ -611,17 +664,20 @@ def list_items_live( cms_locale_id : typing.Optional[str] Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) name : typing.Optional[str] - The name of the item(s) + Filter by the exact name of the item(s) slug : typing.Optional[str] - The slug of the item + Filter by the exact slug of the item + + last_published : typing.Optional[ItemsListItemsLiveRequestLastPublished] + Filter by the last published date of the item(s) sort_by : typing.Optional[ItemsListItemsLiveRequestSortBy] Sort results by the provided value @@ -646,10 +702,18 @@ def list_items_live( ) client.collections.items.list_items_live( collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_id="cmsLocaleId", + offset=1, + limit=1, + name="name", + slug="slug", + sort_by="lastPublished", + sort_order="asc", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().data_api, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -657,6 +721,9 @@ def list_items_live( "limit": limit, "name": name, "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsLiveRequestLastPublished, direction="write" + ), "sortBy": sort_by, "sortOrder": sort_order, }, @@ -730,14 +797,15 @@ def create_item_live( self, collection_id: str, *, - request: ItemsCreateItemLiveRequest, + request: ItemsCreateItemLiveRequestBody, + skip_invalid_files: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ - Create live Item(s) in a Collection. The Item(s) will be published to the live site. + Create item(s) in a collection that will be immediately published to the live site. - To create items across multiple locales, [please use this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + To create items across multiple locales, [please use this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write` @@ -747,7 +815,10 @@ def create_item_live( collection_id : str Unique identifier for a Collection - request : ItemsCreateItemLiveRequest + request : ItemsCreateItemLiveRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -766,21 +837,26 @@ def create_item_live( ) client.collections.items.create_item_live( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, request=CollectionItem( is_archived=False, is_draft=False, field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", + name="The Hitchhiker's Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", ), ), ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemLiveRequest, direction="write" + object_=request, annotation=ItemsCreateItemLiveRequestBody, direction="write" ), request_options=request_options, omit=OMIT, @@ -853,13 +929,13 @@ def delete_items_live( self, collection_id: str, *, - items: typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] = OMIT, + items: typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Remove an item or multiple items (up to 100 items) from the live site. Deleting published items will unpublish the items from the live site and set them to draft. + Unpublish up to 100 items from the live site and set the `isDraft` property to `true`. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be unpublished only in the primary locale. + Items will only be unpublished in the primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -868,7 +944,7 @@ def delete_items_live( collection_id : str Unique identifier for a Collection - items : typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] + items : typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -880,16 +956,25 @@ def delete_items_live( Examples -------- from webflow import Webflow + from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsLiveRequestItemsItem, + ) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.delete_items_live( collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsLiveRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="DELETE", json={ "items": convert_and_respect_annotation_metadata( @@ -964,13 +1049,14 @@ def update_items_live( self, collection_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemListNoPagination: """ - Update a single live item or multiple live items (up to 100) in a Collection + Update a single published item or multiple published items (up to 100) in a Collection - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -979,6 +1065,9 @@ def update_items_live( collection_id : str Unique identifier for a Collection + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] request_options : typing.Optional[RequestOptions] @@ -1002,6 +1091,7 @@ def update_items_live( ) client.collections.items.update_items_live( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, items=[ CollectionItemWithIdInput( id="66f6ed9576ddacf3149d5ea6", @@ -1040,7 +1130,11 @@ def update_items_live( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "items": convert_and_respect_annotation_metadata( object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" @@ -1091,6 +1185,16 @@ def update_items_live( ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -1121,6 +1225,7 @@ def create_items( collection_id: str, *, field_data: CreateBulkCollectionItemRequestBodyFieldData, + skip_invalid_files: typing.Optional[bool] = None, cms_locale_ids: typing.Optional[typing.Sequence[str]] = OMIT, is_archived: typing.Optional[bool] = OMIT, is_draft: typing.Optional[bool] = OMIT, @@ -1129,9 +1234,10 @@ def create_items( """ Create an item or multiple items in a CMS Collection across multiple corresponding locales. - **Notes:** + - This endpoint can create up to 100 items in a request. - - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. + - If the `cmsLocaleIds` parameter is not included in the request, an item will only be created in the primary locale. + Required scope | `CMS:write` @@ -1142,6 +1248,9 @@ def create_items( field_data : CreateBulkCollectionItemRequestBodyFieldData + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + cms_locale_ids : typing.Optional[typing.Sequence[str]] Array of identifiers for the locales where the item will be created @@ -1169,6 +1278,7 @@ def create_items( ) client.collections.items.create_items( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, cms_locale_ids=[ "66f6e966c9e1dc700a857ca3", "66f6e966c9e1dc700a857ca4", @@ -1184,7 +1294,11 @@ def create_items( """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/bulk", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "cmsLocaleIds": cms_locale_ids, "isArchived": is_archived, @@ -1305,10 +1419,12 @@ def get_item( client.collections.items.get_item( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -1388,7 +1504,7 @@ def delete_item( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Delete an Item from a Collection. This endpoint does not currently support bulk deletion. + Delete an item from a collection. Required scope | `CMS:write` @@ -1420,10 +1536,12 @@ def delete_item( client.collections.items.delete_item( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", params={ "cmsLocaleId": cms_locale_id, @@ -1493,6 +1611,7 @@ def update_item( collection_id: str, item_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, @@ -1516,6 +1635,9 @@ def update_item( item_id : str Unique identifier for an Item + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + id : typing.Optional[str] Unique identifier for the Item @@ -1557,17 +1679,22 @@ def update_item( client.collections.items.update_item( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + skip_invalid_files=True, is_archived=False, is_draft=False, field_data=CollectionItemPatchSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", + name="The Hitchhiker's Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", ), ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "id": id, "cmsLocaleId": cms_locale_id, @@ -1658,6 +1785,10 @@ def get_item_live( """ Get details of a selected Collection live Item. + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + + Required scope | `CMS:read` Parameters @@ -1689,10 +1820,12 @@ def get_item_live( client.collections.items.get_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().data_api, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -1772,9 +1905,9 @@ def delete_item_live( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. + Unpublish a live item from the site and set the `isDraft` property to `true`. - This endpoint does not currently support bulk deletion. + For bulk unpublishing, please use [this endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) Required scope | `CMS:write` @@ -1806,10 +1939,12 @@ def delete_item_live( client.collections.items.delete_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, method="DELETE", params={ "cmsLocaleId": cms_locale_id, @@ -1879,6 +2014,7 @@ def update_item_live( collection_id: str, item_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, @@ -1902,6 +2038,9 @@ def update_item_live( item_id : str Unique identifier for an Item + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + id : typing.Optional[str] Unique identifier for the Item @@ -1943,17 +2082,22 @@ def update_item_live( client.collections.items.update_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + skip_invalid_files=True, is_archived=False, is_draft=False, field_data=CollectionItemPatchSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", + name="The Hitchhiker's Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", ), ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "id": id, "cmsLocaleId": cms_locale_id, @@ -2008,6 +2152,16 @@ def update_item_live( ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -2037,7 +2191,7 @@ def publish_item( self, collection_id: str, *, - item_ids: typing.Sequence[str], + request: ItemsPublishItemRequest, request_options: typing.Optional[RequestOptions] = None, ) -> ItemsPublishItemResponse: """ @@ -2050,7 +2204,7 @@ def publish_item( collection_id : str Unique identifier for a Collection - item_ids : typing.Sequence[str] + request : ItemsPublishItemRequest request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -2063,24 +2217,29 @@ def publish_item( Examples -------- from webflow import Webflow + from webflow.resources.collections.resources.items import ItemIDs client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.collections.items.publish_item( collection_id="580e63fc8c9a982ac9b8b745", - item_ids=["itemIds"], + request=ItemIDs( + item_ids=[ + "643fd856d66b6528195ee2ca", + "643fd856d66b6528195ee2cb", + "643fd856d66b6528195ee2cc", + ], + ), ) """ _response = self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/publish", + base_url=self._client_wrapper.get_environment().base, method="POST", - json={ - "itemIds": item_ids, - }, - headers={ - "content-type": "application/json", - }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsPublishItemRequest, direction="write" + ), request_options=request_options, omit=OMIT, ) @@ -2168,10 +2327,11 @@ async def list_items( collection_id: str, *, cms_locale_id: typing.Optional[str] = None, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, name: typing.Optional[str] = None, slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsRequestLastPublished] = None, sort_by: typing.Optional[ItemsListItemsRequestSortBy] = None, sort_order: typing.Optional[ItemsListItemsRequestSortOrder] = None, request_options: typing.Optional[RequestOptions] = None, @@ -2189,17 +2349,20 @@ async def list_items( cms_locale_id : typing.Optional[str] Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) name : typing.Optional[str] - The name of the item(s) + Filter by the exact name of the item(s) slug : typing.Optional[str] - The slug of the item + Filter by the exact slug of the item + + last_published : typing.Optional[ItemsListItemsRequestLastPublished] + Filter by the last published date of the item(s) sort_by : typing.Optional[ItemsListItemsRequestSortBy] Sort results by the provided value @@ -2229,6 +2392,13 @@ async def list_items( async def main() -> None: await client.collections.items.list_items( collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_id="cmsLocaleId", + offset=1, + limit=1, + name="name", + slug="slug", + sort_by="lastPublished", + sort_order="asc", ) @@ -2236,6 +2406,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -2243,6 +2414,9 @@ async def main() -> None: "limit": limit, "name": name, "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsRequestLastPublished, direction="write" + ), "sortBy": sort_by, "sortOrder": sort_order, }, @@ -2316,14 +2490,15 @@ async def create_item( self, collection_id: str, *, - request: ItemsCreateItemRequest, + request: ItemsCreateItemRequestBody, + skip_invalid_files: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ Create Item(s) in a Collection. - To create items across multiple locales, please use [this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + To create items across multiple locales, please use [this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write` @@ -2332,7 +2507,10 @@ async def create_item( collection_id : str Unique identifier for a Collection - request : ItemsCreateItemRequest + request : ItemsCreateItemRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -2360,12 +2538,13 @@ async def create_item( async def main() -> None: await client.collections.items.create_item( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, request=CollectionItemPostSingle( is_archived=False, is_draft=False, field_data=CollectionItemPostSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", + name="The Hitchhiker's Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", ), ), ) @@ -2375,9 +2554,13 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemRequest, direction="write" + object_=request, annotation=ItemsCreateItemRequestBody, direction="write" ), request_options=request_options, omit=OMIT, @@ -2450,13 +2633,13 @@ async def delete_items( self, collection_id: str, *, - items: typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] = OMIT, + items: typing.Sequence[ItemsDeleteItemsRequestItemsItem], request_options: typing.Optional[RequestOptions] = None, ) -> None: """ Delete Items from a Collection. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be deleted only in the primary locale. + Items will only be deleted in the primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -2465,7 +2648,7 @@ async def delete_items( collection_id : str Unique identifier for a Collection - items : typing.Optional[typing.Sequence[ItemsDeleteItemsRequestItemsItem]] + items : typing.Sequence[ItemsDeleteItemsRequestItemsItem] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -2479,6 +2662,9 @@ async def delete_items( import asyncio from webflow import AsyncWebflow + from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsRequestItemsItem, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -2488,6 +2674,11 @@ async def delete_items( async def main() -> None: await client.collections.items.delete_items( collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) @@ -2495,6 +2686,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="DELETE", json={ "items": convert_and_respect_annotation_metadata( @@ -2579,13 +2771,16 @@ async def update_items( self, collection_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> CollectionItem: + ) -> ItemsUpdateItemsResponse: """ - Update a single item or multiple items (up to 100) in a Collection. + Update a single item or multiple items in a Collection. + + The limit for this endpoint is 100 items. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -2594,6 +2789,9 @@ async def update_items( collection_id : str Unique identifier for a Collection + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] request_options : typing.Optional[RequestOptions] @@ -2601,7 +2799,7 @@ async def update_items( Returns ------- - CollectionItem + ItemsUpdateItemsResponse Request was successful Examples @@ -2622,6 +2820,7 @@ async def update_items( async def main() -> None: await client.collections.items.update_items( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, items=[ CollectionItemWithIdInput( id="66f6ed9576ddacf3149d5ea6", @@ -2663,7 +2862,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "items": convert_and_respect_annotation_metadata( object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" @@ -2678,9 +2881,9 @@ async def main() -> None: try: if 200 <= _response.status_code < 300: return typing.cast( - CollectionItem, + ItemsUpdateItemsResponse, parse_obj_as( - type_=CollectionItem, # type: ignore + type_=ItemsUpdateItemsResponse, # type: ignore object_=_response.json(), ), ) @@ -2744,16 +2947,21 @@ async def list_items_live( collection_id: str, *, cms_locale_id: typing.Optional[str] = None, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, name: typing.Optional[str] = None, slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsLiveRequestLastPublished] = None, sort_by: typing.Optional[ItemsListItemsLiveRequestSortBy] = None, sort_order: typing.Optional[ItemsListItemsLiveRequestSortOrder] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemList: """ - List of all live Items within a Collection. + List all published items in a collection. + + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + Required scope | `CMS:read` @@ -2765,17 +2973,20 @@ async def list_items_live( cms_locale_id : typing.Optional[str] Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) name : typing.Optional[str] - The name of the item(s) + Filter by the exact name of the item(s) slug : typing.Optional[str] - The slug of the item + Filter by the exact slug of the item + + last_published : typing.Optional[ItemsListItemsLiveRequestLastPublished] + Filter by the last published date of the item(s) sort_by : typing.Optional[ItemsListItemsLiveRequestSortBy] Sort results by the provided value @@ -2805,6 +3016,13 @@ async def list_items_live( async def main() -> None: await client.collections.items.list_items_live( collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_id="cmsLocaleId", + offset=1, + limit=1, + name="name", + slug="slug", + sort_by="lastPublished", + sort_order="asc", ) @@ -2812,6 +3030,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().data_api, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -2819,6 +3038,9 @@ async def main() -> None: "limit": limit, "name": name, "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsLiveRequestLastPublished, direction="write" + ), "sortBy": sort_by, "sortOrder": sort_order, }, @@ -2892,14 +3114,15 @@ async def create_item_live( self, collection_id: str, *, - request: ItemsCreateItemLiveRequest, + request: ItemsCreateItemLiveRequestBody, + skip_invalid_files: typing.Optional[bool] = None, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItem: """ - Create live Item(s) in a Collection. The Item(s) will be published to the live site. + Create item(s) in a collection that will be immediately published to the live site. - To create items across multiple locales, [please use this endpoint.](/v2.0.0/data/reference/cms/collection-items/staged-items/create-items) + To create items across multiple locales, [please use this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) Required scope | `CMS:write` @@ -2909,7 +3132,10 @@ async def create_item_live( collection_id : str Unique identifier for a Collection - request : ItemsCreateItemLiveRequest + request : ItemsCreateItemLiveRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -2933,12 +3159,13 @@ async def create_item_live( async def main() -> None: await client.collections.items.create_item_live( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, request=CollectionItem( is_archived=False, is_draft=False, field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", + name="The Hitchhiker's Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", ), ), ) @@ -2948,9 +3175,13 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemLiveRequest, direction="write" + object_=request, annotation=ItemsCreateItemLiveRequestBody, direction="write" ), request_options=request_options, omit=OMIT, @@ -3023,13 +3254,13 @@ async def delete_items_live( self, collection_id: str, *, - items: typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] = OMIT, + items: typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Remove an item or multiple items (up to 100 items) from the live site. Deleting published items will unpublish the items from the live site and set them to draft. + Unpublish up to 100 items from the live site and set the `isDraft` property to `true`. - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be unpublished only in the primary locale. + Items will only be unpublished in the primary locale unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -3038,7 +3269,7 @@ async def delete_items_live( collection_id : str Unique identifier for a Collection - items : typing.Optional[typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]] + items : typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -3052,6 +3283,9 @@ async def delete_items_live( import asyncio from webflow import AsyncWebflow + from webflow.resources.collections.resources.items import ( + ItemsDeleteItemsLiveRequestItemsItem, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -3061,6 +3295,11 @@ async def delete_items_live( async def main() -> None: await client.collections.items.delete_items_live( collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsLiveRequestItemsItem( + id="580e64008c9a982ac9b8b754", + ) + ], ) @@ -3068,6 +3307,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="DELETE", json={ "items": convert_and_respect_annotation_metadata( @@ -3142,13 +3382,14 @@ async def update_items_live( self, collection_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> CollectionItemListNoPagination: """ - Update a single live item or multiple live items (up to 100) in a Collection + Update a single published item or multiple published items (up to 100) in a Collection - **Note:** If the `cmsLocaleId` parameter is undefined or empty and the items are localized, items will be updated only in the primary locale. + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. Required scope | `CMS:write` @@ -3157,6 +3398,9 @@ async def update_items_live( collection_id : str Unique identifier for a Collection + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] request_options : typing.Optional[RequestOptions] @@ -3185,6 +3429,7 @@ async def update_items_live( async def main() -> None: await client.collections.items.update_items_live( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, items=[ CollectionItemWithIdInput( id="66f6ed9576ddacf3149d5ea6", @@ -3226,7 +3471,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "items": convert_and_respect_annotation_metadata( object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" @@ -3277,6 +3526,16 @@ async def main() -> None: ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -3307,6 +3566,7 @@ async def create_items( collection_id: str, *, field_data: CreateBulkCollectionItemRequestBodyFieldData, + skip_invalid_files: typing.Optional[bool] = None, cms_locale_ids: typing.Optional[typing.Sequence[str]] = OMIT, is_archived: typing.Optional[bool] = OMIT, is_draft: typing.Optional[bool] = OMIT, @@ -3315,9 +3575,10 @@ async def create_items( """ Create an item or multiple items in a CMS Collection across multiple corresponding locales. - **Notes:** + - This endpoint can create up to 100 items in a request. - - If the `cmsLocaleIds` parameter is undefined or empty and localization is enabled, items will only be created in the primary locale. + - If the `cmsLocaleIds` parameter is not included in the request, an item will only be created in the primary locale. + Required scope | `CMS:write` @@ -3328,6 +3589,9 @@ async def create_items( field_data : CreateBulkCollectionItemRequestBodyFieldData + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + cms_locale_ids : typing.Optional[typing.Sequence[str]] Array of identifiers for the locales where the item will be created @@ -3360,6 +3624,7 @@ async def create_items( async def main() -> None: await client.collections.items.create_items( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, cms_locale_ids=[ "66f6e966c9e1dc700a857ca3", "66f6e966c9e1dc700a857ca4", @@ -3378,7 +3643,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/bulk", + base_url=self._client_wrapper.get_environment().base, method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "cmsLocaleIds": cms_locale_ids, "isArchived": is_archived, @@ -3504,6 +3773,7 @@ async def main() -> None: await client.collections.items.get_item( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) @@ -3511,6 +3781,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -3590,7 +3861,7 @@ async def delete_item( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Delete an Item from a Collection. This endpoint does not currently support bulk deletion. + Delete an item from a collection. Required scope | `CMS:write` @@ -3627,6 +3898,7 @@ async def main() -> None: await client.collections.items.delete_item( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) @@ -3634,6 +3906,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", params={ "cmsLocaleId": cms_locale_id, @@ -3703,6 +3976,7 @@ async def update_item( collection_id: str, item_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, @@ -3726,6 +4000,9 @@ async def update_item( item_id : str Unique identifier for an Item + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + id : typing.Optional[str] Unique identifier for the Item @@ -3772,11 +4049,12 @@ async def main() -> None: await client.collections.items.update_item( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + skip_invalid_files=True, is_archived=False, is_draft=False, field_data=CollectionItemPatchSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", + name="The Hitchhiker's Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", ), ) @@ -3785,7 +4063,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "id": id, "cmsLocaleId": cms_locale_id, @@ -3876,6 +4158,10 @@ async def get_item_live( """ Get details of a selected Collection live Item. + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + + Required scope | `CMS:read` Parameters @@ -3912,6 +4198,7 @@ async def main() -> None: await client.collections.items.get_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) @@ -3919,6 +4206,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().data_api, method="GET", params={ "cmsLocaleId": cms_locale_id, @@ -3998,9 +4286,9 @@ async def delete_item_live( request_options: typing.Optional[RequestOptions] = None, ) -> None: """ - Remove a live item from the site. Removing a published item will unpublish the item from the live site and set it to draft. + Unpublish a live item from the site and set the `isDraft` property to `true`. - This endpoint does not currently support bulk deletion. + For bulk unpublishing, please use [this endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) Required scope | `CMS:write` @@ -4037,6 +4325,7 @@ async def main() -> None: await client.collections.items.delete_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + cms_locale_id="cmsLocaleId", ) @@ -4044,6 +4333,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, method="DELETE", params={ "cmsLocaleId": cms_locale_id, @@ -4113,6 +4403,7 @@ async def update_item_live( collection_id: str, item_id: str, *, + skip_invalid_files: typing.Optional[bool] = None, id: typing.Optional[str] = OMIT, cms_locale_id: typing.Optional[str] = OMIT, last_published: typing.Optional[str] = OMIT, @@ -4136,6 +4427,9 @@ async def update_item_live( item_id : str Unique identifier for an Item + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + id : typing.Optional[str] Unique identifier for the Item @@ -4182,11 +4476,12 @@ async def main() -> None: await client.collections.items.update_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + skip_invalid_files=True, is_archived=False, is_draft=False, field_data=CollectionItemPatchSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", - slug="pan-galactic-gargle-blaster", + name="The Hitchhiker's Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", ), ) @@ -4195,7 +4490,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, json={ "id": id, "cmsLocaleId": cms_locale_id, @@ -4250,6 +4549,16 @@ async def main() -> None: ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -4279,7 +4588,7 @@ async def publish_item( self, collection_id: str, *, - item_ids: typing.Sequence[str], + request: ItemsPublishItemRequest, request_options: typing.Optional[RequestOptions] = None, ) -> ItemsPublishItemResponse: """ @@ -4292,7 +4601,7 @@ async def publish_item( collection_id : str Unique identifier for a Collection - item_ids : typing.Sequence[str] + request : ItemsPublishItemRequest request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -4307,6 +4616,7 @@ async def publish_item( import asyncio from webflow import AsyncWebflow + from webflow.resources.collections.resources.items import ItemIDs client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -4316,7 +4626,13 @@ async def publish_item( async def main() -> None: await client.collections.items.publish_item( collection_id="580e63fc8c9a982ac9b8b745", - item_ids=["itemIds"], + request=ItemIDs( + item_ids=[ + "643fd856d66b6528195ee2ca", + "643fd856d66b6528195ee2cb", + "643fd856d66b6528195ee2cc", + ], + ), ) @@ -4324,13 +4640,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"collections/{jsonable_encoder(collection_id)}/items/publish", + base_url=self._client_wrapper.get_environment().base, method="POST", - json={ - "itemIds": item_ids, - }, - headers={ - "content-type": "application/json", - }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsPublishItemRequest, direction="write" + ), request_options=request_options, omit=OMIT, ) diff --git a/src/webflow/resources/collections/resources/items/types/__init__.py b/src/webflow/resources/collections/resources/items/types/__init__.py index 67040fb..2d9a604 100644 --- a/src/webflow/resources/collections/resources/items/types/__init__.py +++ b/src/webflow/resources/collections/resources/items/types/__init__.py @@ -2,15 +2,20 @@ from .create_bulk_collection_item_request_body_field_data import CreateBulkCollectionItemRequestBodyFieldData from .create_bulk_collection_item_request_body_field_data_item import CreateBulkCollectionItemRequestBodyFieldDataItem -from .items_create_item_live_request import ItemsCreateItemLiveRequest -from .items_create_item_request import ItemsCreateItemRequest +from .item_i_ds import ItemIDs +from .item_i_ds_with_locales import ItemIDsWithLocales +from .items_create_item_live_request_body import ItemsCreateItemLiveRequestBody +from .items_create_item_request_body import ItemsCreateItemRequestBody from .items_delete_items_live_request_items_item import ItemsDeleteItemsLiveRequestItemsItem from .items_delete_items_request_items_item import ItemsDeleteItemsRequestItemsItem from .items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy from .items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder from .items_list_items_request_sort_by import ItemsListItemsRequestSortBy from .items_list_items_request_sort_order import ItemsListItemsRequestSortOrder +from .items_publish_item_request import ItemsPublishItemRequest +from .items_publish_item_request_items_items_item import ItemsPublishItemRequestItemsItemsItem from .items_publish_item_response import ItemsPublishItemResponse +from .items_update_items_response import ItemsUpdateItemsResponse from .multiple_items import MultipleItems from .multiple_live_items import MultipleLiveItems from .single_cms_item import SingleCmsItem @@ -18,15 +23,20 @@ __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", "CreateBulkCollectionItemRequestBodyFieldDataItem", - "ItemsCreateItemLiveRequest", - "ItemsCreateItemRequest", + "ItemIDs", + "ItemIDsWithLocales", + "ItemsCreateItemLiveRequestBody", + "ItemsCreateItemRequestBody", "ItemsDeleteItemsLiveRequestItemsItem", "ItemsDeleteItemsRequestItemsItem", "ItemsListItemsLiveRequestSortBy", "ItemsListItemsLiveRequestSortOrder", "ItemsListItemsRequestSortBy", "ItemsListItemsRequestSortOrder", + "ItemsPublishItemRequest", + "ItemsPublishItemRequestItemsItemsItem", "ItemsPublishItemResponse", + "ItemsUpdateItemsResponse", "MultipleItems", "MultipleLiveItems", "SingleCmsItem", diff --git a/src/webflow/resources/collections/resources/items/types/item_i_ds.py b/src/webflow/resources/collections/resources/items/types/item_i_ds.py new file mode 100644 index 0000000..b9b138e --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/item_i_ds.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ......core.serialization import FieldMetadata +from ......core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ItemIDs(UniversalBaseModel): + """ + An array of Item IDs in a single locale + """ + + item_ids: typing_extensions.Annotated[typing.Optional[typing.List[str]], FieldMetadata(alias="itemIds")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py b/src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py new file mode 100644 index 0000000..ba98ae7 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import typing +from .items_publish_item_request_items_items_item import ItemsPublishItemRequestItemsItemsItem +from ......core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ItemIDsWithLocales(UniversalBaseModel): + """ + An array of Item IDs with included `cmsLocaleIds` + """ + + items: typing.Optional[typing.List[ItemsPublishItemRequestItemsItemsItem]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/items_create_item_live_request.py b/src/webflow/resources/collections/resources/items/types/items_create_item_live_request_body.py similarity index 69% rename from src/webflow/resources/collections/resources/items/types/items_create_item_live_request.py rename to src/webflow/resources/collections/resources/items/types/items_create_item_live_request_body.py index dc2f963..348e0be 100644 --- a/src/webflow/resources/collections/resources/items/types/items_create_item_live_request.py +++ b/src/webflow/resources/collections/resources/items/types/items_create_item_live_request_body.py @@ -4,4 +4,4 @@ from ......types.collection_item import CollectionItem from .multiple_live_items import MultipleLiveItems -ItemsCreateItemLiveRequest = typing.Union[CollectionItem, MultipleLiveItems] +ItemsCreateItemLiveRequestBody = typing.Union[CollectionItem, MultipleLiveItems] diff --git a/src/webflow/resources/collections/resources/items/types/items_create_item_request.py b/src/webflow/resources/collections/resources/items/types/items_create_item_request_body.py similarity index 70% rename from src/webflow/resources/collections/resources/items/types/items_create_item_request.py rename to src/webflow/resources/collections/resources/items/types/items_create_item_request_body.py index 7627c55..af4860a 100644 --- a/src/webflow/resources/collections/resources/items/types/items_create_item_request.py +++ b/src/webflow/resources/collections/resources/items/types/items_create_item_request_body.py @@ -4,4 +4,4 @@ from ......types.collection_item_post_single import CollectionItemPostSingle from .multiple_items import MultipleItems -ItemsCreateItemRequest = typing.Union[CollectionItemPostSingle, MultipleItems] +ItemsCreateItemRequestBody = typing.Union[CollectionItemPostSingle, MultipleItems] diff --git a/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py b/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py index 63e00bc..544df88 100644 --- a/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py +++ b/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py @@ -1,15 +1,15 @@ # This file was auto-generated by Fern from our API Definition. from ......core.pydantic_utilities import UniversalBaseModel -import typing_extensions -from ......core.serialization import FieldMetadata import pydantic +import typing_extensions import typing +from ......core.serialization import FieldMetadata from ......core.pydantic_utilities import IS_PYDANTIC_V2 class ItemsDeleteItemsLiveRequestItemsItem(UniversalBaseModel): - item_id: typing_extensions.Annotated[str, FieldMetadata(alias="itemId")] = pydantic.Field() + id: str = pydantic.Field() """ Unique identifier for the Item """ diff --git a/src/webflow/resources/collections/resources/items/types/items_publish_item_request.py b/src/webflow/resources/collections/resources/items/types/items_publish_item_request.py new file mode 100644 index 0000000..4f7a82b --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_publish_item_request.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .item_i_ds import ItemIDs +from .item_i_ds_with_locales import ItemIDsWithLocales + +ItemsPublishItemRequest = typing.Union[ItemIDs, ItemIDsWithLocales] diff --git a/src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py b/src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py new file mode 100644 index 0000000..08b2e17 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from ......core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +import typing +from ......core.serialization import FieldMetadata +from ......core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ItemsPublishItemRequestItemsItemsItem(UniversalBaseModel): + id: str = pydantic.Field() + """ + The ID of the CMS item + """ + + cms_locale_ids: typing_extensions.Annotated[ + typing.Optional[typing.List[str]], FieldMetadata(alias="cmsLocaleIds") + ] = pydantic.Field(default=None) + """ + Array of identifiers for the locales where the item will be published + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/items/types/items_update_items_response.py b/src/webflow/resources/collections/resources/items/types/items_update_items_response.py new file mode 100644 index 0000000..c073f18 --- /dev/null +++ b/src/webflow/resources/collections/resources/items/types/items_update_items_response.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from ......types.collection_item import CollectionItem +from ......types.collection_item_list import CollectionItemList + +ItemsUpdateItemsResponse = typing.Union[CollectionItem, CollectionItemList] diff --git a/src/webflow/resources/components/client.py b/src/webflow/resources/components/client.py index ef50ac9..5437017 100644 --- a/src/webflow/resources/components/client.py +++ b/src/webflow/resources/components/client.py @@ -36,8 +36,9 @@ def list( self, site_id: str, *, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentList: """ @@ -50,10 +51,13 @@ def list( site_id : str Unique identifier for a Site - limit : typing.Optional[float] + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -73,12 +77,17 @@ def list( ) client.components.list( site_id="580e63e98c9a982ac9b8b741", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -154,12 +163,13 @@ def get_content( component_id: str, *, locale_id: typing.Optional[str] = None, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentDom: """ - Get static content from a component definition. This includes text nodes, image nodes and nested component instances. + Get static content from a component definition. This includes text nodes, image nodes, select nodes, text input nodes, submit button nodes, and nested component instances. To retrieve dynamic content set by component properties, use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. @@ -175,12 +185,17 @@ def get_content( Unique identifier for a Component locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) - limit : typing.Optional[float] + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -202,13 +217,18 @@ def get_content( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -285,14 +305,16 @@ def update_content( *, nodes: typing.Sequence[ComponentDomWriteNodesItem], locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentsUpdateContentResponse: """ This endpoint updates content within a component defintion for **secondary locales**. It supports updating up to 1000 nodes in a single request. Before making updates: - 1. Use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint to identify available content nodes and their types - 2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint + 1. Use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint to identify available content nodes and their types. + 2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + 3. DOM elements may include a `data-w-id` attribute. This attribute is used by Webflow to maintain custom attributes and links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. This endpoint is specifically for localizing component definitions. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. @@ -312,7 +334,12 @@ def update_content( List of DOM Nodes with the new content that will be updated in each node. locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -327,6 +354,10 @@ def update_content( from webflow import ( ComponentInstanceNodePropertyOverridesWrite, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + Select, + SelectNodeWriteChoicesItem, + SubmitButtonNodeWrite, + TextInputNodeWrite, TextNodeWrite, Webflow, ) @@ -338,6 +369,7 @@ def update_content( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", nodes=[ TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", @@ -347,6 +379,28 @@ def update_content( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Don't Panic!

Always know where your towel is.

", ), + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInputNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButtonNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), ComponentInstanceNodePropertyOverridesWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ @@ -365,9 +419,11 @@ def update_content( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, + "branchId": branch_id, }, json={ "nodes": convert_and_respect_annotation_metadata( @@ -460,14 +516,15 @@ def get_properties( component_id: str, *, locale_id: typing.Optional[str] = None, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentProperties: """ - Get the property default values of a component definition. + Get the default property values of a component definition. - If you do not provide a Locale ID in your request, the response will return any properties that can be localized from the Primary locale. + If you do not include a `localeId` in your request, the response will return any properties that can be localized from the Primary locale. Required scope | `components:read` @@ -480,12 +537,17 @@ def get_properties( Unique identifier for a Component locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) - limit : typing.Optional[float] + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -507,13 +569,18 @@ def get_properties( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -590,15 +657,17 @@ def update_properties( *, properties: typing.Sequence[ComponentPropertiesWritePropertiesItem], locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentsUpdatePropertiesResponse: """ - Update the property default values of a component definition in a specificed locale. + Update the default property values of a component definition in a specificed locale. Before making updates: - 1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify available properties + 1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify properties that can be updated in a secondary locale. + 2. Rich Text properties may include a `data-w-id` attribute. This attribute is used by Webflow to maintain links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. - The request requires a secondary locale ID. If a locale is missing, the request will not be processed and will result in an error. + The request requires a secondary locale ID. If a `localeId` is missing, the request will not be processed and will result in an error. Required scope | `components:write` @@ -614,7 +683,12 @@ def update_properties( A list of component properties to update within the specified secondary locale. locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -636,6 +710,7 @@ def update_properties( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", properties=[ ComponentPropertiesWritePropertiesItem( property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", @@ -650,9 +725,11 @@ def update_properties( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, + "branchId": branch_id, }, json={ "properties": convert_and_respect_annotation_metadata( @@ -740,8 +817,9 @@ async def list( self, site_id: str, *, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentList: """ @@ -754,10 +832,13 @@ async def list( site_id : str Unique identifier for a Site - limit : typing.Optional[float] + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -782,6 +863,9 @@ async def list( async def main() -> None: await client.components.list( site_id="580e63e98c9a982ac9b8b741", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) @@ -789,8 +873,10 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -866,12 +952,13 @@ async def get_content( component_id: str, *, locale_id: typing.Optional[str] = None, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentDom: """ - Get static content from a component definition. This includes text nodes, image nodes and nested component instances. + Get static content from a component definition. This includes text nodes, image nodes, select nodes, text input nodes, submit button nodes, and nested component instances. To retrieve dynamic content set by component properties, use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. @@ -887,12 +974,17 @@ async def get_content( Unique identifier for a Component locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) - limit : typing.Optional[float] + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -919,6 +1011,9 @@ async def main() -> None: site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) @@ -926,9 +1021,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -1005,14 +1102,16 @@ async def update_content( *, nodes: typing.Sequence[ComponentDomWriteNodesItem], locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentsUpdateContentResponse: """ This endpoint updates content within a component defintion for **secondary locales**. It supports updating up to 1000 nodes in a single request. Before making updates: - 1. Use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint to identify available content nodes and their types - 2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint + 1. Use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint to identify available content nodes and their types. + 2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + 3. DOM elements may include a `data-w-id` attribute. This attribute is used by Webflow to maintain custom attributes and links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. This endpoint is specifically for localizing component definitions. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. @@ -1032,7 +1131,12 @@ async def update_content( List of DOM Nodes with the new content that will be updated in each node. locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1050,6 +1154,10 @@ async def update_content( AsyncWebflow, ComponentInstanceNodePropertyOverridesWrite, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + Select, + SelectNodeWriteChoicesItem, + SubmitButtonNodeWrite, + TextInputNodeWrite, TextNodeWrite, ) @@ -1063,6 +1171,7 @@ async def main() -> None: site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", nodes=[ TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", @@ -1072,6 +1181,28 @@ async def main() -> None: node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Don't Panic!

Always know where your towel is.

", ), + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInputNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButtonNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), ComponentInstanceNodePropertyOverridesWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ @@ -1093,9 +1224,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, + "branchId": branch_id, }, json={ "nodes": convert_and_respect_annotation_metadata( @@ -1188,14 +1321,15 @@ async def get_properties( component_id: str, *, locale_id: typing.Optional[str] = None, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentProperties: """ - Get the property default values of a component definition. + Get the default property values of a component definition. - If you do not provide a Locale ID in your request, the response will return any properties that can be localized from the Primary locale. + If you do not include a `localeId` in your request, the response will return any properties that can be localized from the Primary locale. Required scope | `components:read` @@ -1208,12 +1342,17 @@ async def get_properties( Unique identifier for a Component locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) - limit : typing.Optional[float] + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -1240,6 +1379,9 @@ async def main() -> None: site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) @@ -1247,9 +1389,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, + "branchId": branch_id, "limit": limit, "offset": offset, }, @@ -1326,15 +1470,17 @@ async def update_properties( *, properties: typing.Sequence[ComponentPropertiesWritePropertiesItem], locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ComponentsUpdatePropertiesResponse: """ - Update the property default values of a component definition in a specificed locale. + Update the default property values of a component definition in a specificed locale. Before making updates: - 1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify available properties + 1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify properties that can be updated in a secondary locale. + 2. Rich Text properties may include a `data-w-id` attribute. This attribute is used by Webflow to maintain links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. - The request requires a secondary locale ID. If a locale is missing, the request will not be processed and will result in an error. + The request requires a secondary locale ID. If a `localeId` is missing, the request will not be processed and will result in an error. Required scope | `components:write` @@ -1350,7 +1496,12 @@ async def update_properties( A list of component properties to update within the specified secondary locale. locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1377,6 +1528,7 @@ async def main() -> None: site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", properties=[ ComponentPropertiesWritePropertiesItem( property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", @@ -1394,9 +1546,11 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, + "branchId": branch_id, }, json={ "properties": convert_and_respect_annotation_metadata( diff --git a/src/webflow/resources/components/types/component_dom_write_nodes_item.py b/src/webflow/resources/components/types/component_dom_write_nodes_item.py index 27888e6..1b1789c 100644 --- a/src/webflow/resources/components/types/component_dom_write_nodes_item.py +++ b/src/webflow/resources/components/types/component_dom_write_nodes_item.py @@ -3,5 +3,16 @@ import typing from ....types.text_node_write import TextNodeWrite from ....types.component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite +from ....types.select import Select +from ....types.text_input_node_write import TextInputNodeWrite +from ....types.submit_button_node_write import SubmitButtonNodeWrite +from ....types.search_button_node_write import SearchButtonNodeWrite -ComponentDomWriteNodesItem = typing.Union[TextNodeWrite, ComponentInstanceNodePropertyOverridesWrite] +ComponentDomWriteNodesItem = typing.Union[ + TextNodeWrite, + ComponentInstanceNodePropertyOverridesWrite, + Select, + TextInputNodeWrite, + SubmitButtonNodeWrite, + SearchButtonNodeWrite, +] diff --git a/src/webflow/resources/ecommerce/client.py b/src/webflow/resources/ecommerce/client.py index bbd3a5d..04ddba6 100644 --- a/src/webflow/resources/ecommerce/client.py +++ b/src/webflow/resources/ecommerce/client.py @@ -57,6 +57,7 @@ def get_settings( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -191,6 +192,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) diff --git a/src/webflow/resources/forms/client.py b/src/webflow/resources/forms/client.py index 515b631..40741cb 100644 --- a/src/webflow/resources/forms/client.py +++ b/src/webflow/resources/forms/client.py @@ -33,8 +33,8 @@ def list( self, site_id: str, *, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> FormList: """ @@ -47,10 +47,10 @@ def list( site_id : str Unique identifier for a Site - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -70,10 +70,13 @@ def list( ) client.forms.list( site_id="580e63e98c9a982ac9b8b741", + limit=1, + offset=1, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/forms", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "limit": limit, @@ -197,6 +200,7 @@ def get(self, form_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"forms/{jsonable_encoder(form_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -278,13 +282,19 @@ def list_submissions( self, form_id: str, *, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> FormSubmissionList: """ List form submissions for a given form + + When a form is used in a component definition, each instance of the form is considered a unique form. + + To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. + + Required scope | `forms:read` Parameters @@ -292,10 +302,10 @@ def list_submissions( form_id : str Unique identifier for a Form - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) request_options : typing.Optional[RequestOptions] @@ -315,10 +325,13 @@ def list_submissions( ) client.forms.list_submissions( form_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) """ _response = self._client_wrapper.httpx_client.request( f"forms/{jsonable_encoder(form_id)}/submissions", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -434,6 +447,7 @@ def get_submission( """ _response = self._client_wrapper.httpx_client.request( f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -511,6 +525,122 @@ def get_submission( raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + def delete_submission( + self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Delete a form submission + + + Required scope | `forms:write` + + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.forms.delete_submission( + form_submission_id="580e63e98c9a982ac9b8b741", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + def update_submission( self, form_submission_id: str, @@ -552,6 +682,7 @@ def update_submission( """ _response = self._client_wrapper.httpx_client.request( f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "formSubmissionData": form_submission_data, @@ -655,8 +786,8 @@ async def list( self, site_id: str, *, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> FormList: """ @@ -669,10 +800,10 @@ async def list( site_id : str Unique identifier for a Site - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -697,6 +828,8 @@ async def list( async def main() -> None: await client.forms.list( site_id="580e63e98c9a982ac9b8b741", + limit=1, + offset=1, ) @@ -704,6 +837,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/forms", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "limit": limit, @@ -835,6 +969,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"forms/{jsonable_encoder(form_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -916,13 +1051,19 @@ async def list_submissions( self, form_id: str, *, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> FormSubmissionList: """ List form submissions for a given form + + When a form is used in a component definition, each instance of the form is considered a unique form. + + To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. + + Required scope | `forms:read` Parameters @@ -930,10 +1071,10 @@ async def list_submissions( form_id : str Unique identifier for a Form - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) request_options : typing.Optional[RequestOptions] @@ -958,6 +1099,8 @@ async def list_submissions( async def main() -> None: await client.forms.list_submissions( form_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) @@ -965,6 +1108,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"forms/{jsonable_encoder(form_id)}/submissions", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -1088,6 +1232,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1165,6 +1310,130 @@ async def main() -> None: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) + async def delete_submission( + self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Delete a form submission + + + Required scope | `forms:write` + + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.forms.delete_submission( + form_submission_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 403: + raise ForbiddenError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + async def update_submission( self, form_submission_id: str, @@ -1214,6 +1483,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "formSubmissionData": form_submission_data, diff --git a/src/webflow/resources/inventory/__init__.py b/src/webflow/resources/inventory/__init__.py index f95deee..e76ae2e 100644 --- a/src/webflow/resources/inventory/__init__.py +++ b/src/webflow/resources/inventory/__init__.py @@ -1,5 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .types import InventoryUpdateRequestInventoryType +from .types import EcommInventoryChangedPayload, InventoryUpdateRequestInventoryType -__all__ = ["InventoryUpdateRequestInventoryType"] +__all__ = ["EcommInventoryChangedPayload", "InventoryUpdateRequestInventoryType"] diff --git a/src/webflow/resources/inventory/client.py b/src/webflow/resources/inventory/client.py index 27e4f3c..db582a9 100644 --- a/src/webflow/resources/inventory/client.py +++ b/src/webflow/resources/inventory/client.py @@ -28,7 +28,7 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper def list( - self, collection_id: str, item_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, sku_collection_id: str, sku_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> InventoryItem: """ List the current inventory levels for a particular SKU item. @@ -37,11 +37,11 @@ def list( Parameters ---------- - collection_id : str - Unique identifier for a Collection + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. - item_id : str - Unique identifier for an Item + sku_id : str + Unique identifier for a SKU request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -59,12 +59,13 @@ def list( access_token="YOUR_ACCESS_TOKEN", ) client.inventory.list( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", ) """ _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -154,8 +155,8 @@ def list( def update( self, - collection_id: str, - item_id: str, + sku_collection_id: str, + sku_id: str, *, inventory_type: InventoryUpdateRequestInventoryType, update_quantity: typing.Optional[float] = OMIT, @@ -173,11 +174,11 @@ def update( Parameters ---------- - collection_id : str - Unique identifier for a Collection + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. - item_id : str - Unique identifier for an Item + sku_id : str + Unique identifier for a SKU inventory_type : InventoryUpdateRequestInventoryType infinite or finite @@ -204,13 +205,14 @@ def update( access_token="YOUR_ACCESS_TOKEN", ) client.inventory.update( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", inventory_type="infinite", ) """ _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "inventoryType": inventory_type, @@ -313,7 +315,7 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper async def list( - self, collection_id: str, item_id: str, *, request_options: typing.Optional[RequestOptions] = None + self, sku_collection_id: str, sku_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> InventoryItem: """ List the current inventory levels for a particular SKU item. @@ -322,11 +324,11 @@ async def list( Parameters ---------- - collection_id : str - Unique identifier for a Collection + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. - item_id : str - Unique identifier for an Item + sku_id : str + Unique identifier for a SKU request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -349,15 +351,16 @@ async def list( async def main() -> None: await client.inventory.list( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", ) asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -447,8 +450,8 @@ async def main() -> None: async def update( self, - collection_id: str, - item_id: str, + sku_collection_id: str, + sku_id: str, *, inventory_type: InventoryUpdateRequestInventoryType, update_quantity: typing.Optional[float] = OMIT, @@ -466,11 +469,11 @@ async def update( Parameters ---------- - collection_id : str - Unique identifier for a Collection + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. - item_id : str - Unique identifier for an Item + sku_id : str + Unique identifier for a SKU inventory_type : InventoryUpdateRequestInventoryType infinite or finite @@ -502,8 +505,8 @@ async def update( async def main() -> None: await client.inventory.update( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", + sku_collection_id="6377a7c4b7a79608c34a46f7", + sku_id="5e8518516e147040726cc415", inventory_type="infinite", ) @@ -511,7 +514,8 @@ async def main() -> None: asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/inventory", + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "inventoryType": inventory_type, diff --git a/src/webflow/resources/inventory/types/__init__.py b/src/webflow/resources/inventory/types/__init__.py index e929f4e..4cf7822 100644 --- a/src/webflow/resources/inventory/types/__init__.py +++ b/src/webflow/resources/inventory/types/__init__.py @@ -1,5 +1,6 @@ # This file was auto-generated by Fern from our API Definition. +from .ecomm_inventory_changed_payload import EcommInventoryChangedPayload from .inventory_update_request_inventory_type import InventoryUpdateRequestInventoryType -__all__ = ["InventoryUpdateRequestInventoryType"] +__all__ = ["EcommInventoryChangedPayload", "InventoryUpdateRequestInventoryType"] diff --git a/src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py b/src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py new file mode 100644 index 0000000..f4a969e --- /dev/null +++ b/src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....core.serialization import FieldMetadata +from ....types.inventory_item import InventoryItem +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class EcommInventoryChangedPayload(UniversalBaseModel): + trigger_type: typing_extensions.Annotated[ + typing.Optional[typing.Literal["ecomm_inventory_changed"]], FieldMetadata(alias="triggerType") + ] = None + payload: typing.Optional[InventoryItem] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/orders/client.py b/src/webflow/resources/orders/client.py index 4aa4b77..b4f39a2 100644 --- a/src/webflow/resources/orders/client.py +++ b/src/webflow/resources/orders/client.py @@ -34,8 +34,8 @@ def list( site_id: str, *, status: typing.Optional[OrdersListRequestStatus] = None, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> OrderList: """ @@ -51,10 +51,10 @@ def list( status : typing.Optional[OrdersListRequestStatus] Filter the orders by status - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) request_options : typing.Optional[RequestOptions] @@ -74,10 +74,14 @@ def list( ) client.orders.list( site_id="580e63e98c9a982ac9b8b741", + status="pending", + offset=1, + limit=1, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "status": status, @@ -207,6 +211,7 @@ def get(self, site_id: str, order_id: str, *, request_options: typing.Optional[R """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -354,6 +359,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "comment": comment, @@ -497,6 +503,7 @@ def update_fulfill( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "sendOrderFulfilledEmail": send_order_fulfilled_email, @@ -629,6 +636,7 @@ def update_unfulfill( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", + base_url=self._client_wrapper.get_environment().base, method="POST", request_options=request_options, ) @@ -763,6 +771,7 @@ def refund( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "reason": reason, @@ -867,8 +876,8 @@ async def list( site_id: str, *, status: typing.Optional[OrdersListRequestStatus] = None, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> OrderList: """ @@ -884,10 +893,10 @@ async def list( status : typing.Optional[OrdersListRequestStatus] Filter the orders by status - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) request_options : typing.Optional[RequestOptions] @@ -912,6 +921,9 @@ async def list( async def main() -> None: await client.orders.list( site_id="580e63e98c9a982ac9b8b741", + status="pending", + offset=1, + limit=1, ) @@ -919,6 +931,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "status": status, @@ -1058,6 +1071,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1213,6 +1227,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "comment": comment, @@ -1364,6 +1379,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "sendOrderFulfilledEmail": send_order_fulfilled_email, @@ -1504,6 +1520,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", + base_url=self._client_wrapper.get_environment().base, method="POST", request_options=request_options, ) @@ -1646,6 +1663,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "reason": reason, diff --git a/src/webflow/resources/pages/__init__.py b/src/webflow/resources/pages/__init__.py index 0fed8e6..898d3de 100644 --- a/src/webflow/resources/pages/__init__.py +++ b/src/webflow/resources/pages/__init__.py @@ -1,6 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from .types import PageDomWriteNodesItem, UpdateStaticContentResponse +from .types import PageDomWriteNodesItem, PageMetadataWriteOpenGraph, PageMetadataWriteSeo, UpdateStaticContentResponse from .resources import scripts -__all__ = ["PageDomWriteNodesItem", "UpdateStaticContentResponse", "scripts"] +__all__ = [ + "PageDomWriteNodesItem", + "PageMetadataWriteOpenGraph", + "PageMetadataWriteSeo", + "UpdateStaticContentResponse", + "scripts", +] diff --git a/src/webflow/resources/pages/client.py b/src/webflow/resources/pages/client.py index 851f4e7..fb5fe60 100644 --- a/src/webflow/resources/pages/client.py +++ b/src/webflow/resources/pages/client.py @@ -16,9 +16,8 @@ from json.decoder import JSONDecodeError from ...core.api_error import ApiError from ...types.page import Page -import datetime as dt -from ...types.page_seo import PageSeo -from ...types.page_open_graph import PageOpenGraph +from .types.page_metadata_write_seo import PageMetadataWriteSeo +from .types.page_metadata_write_open_graph import PageMetadataWriteOpenGraph from ...core.serialization import convert_and_respect_annotation_metadata from ...types.dom import Dom from ...errors.forbidden_error import ForbiddenError @@ -41,8 +40,8 @@ def list( site_id: str, *, locale_id: typing.Optional[str] = None, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> PageList: """ @@ -56,12 +55,14 @@ def list( Unique identifier for a Site locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. - limit : typing.Optional[float] + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -82,10 +83,13 @@ def list( client.pages.list( site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0", + limit=1, + offset=1, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/pages", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -176,7 +180,9 @@ def get_metadata( Unique identifier for a Page locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -200,6 +206,7 @@ def get_metadata( """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -274,24 +281,11 @@ def update_page_settings( self, page_id: str, *, - id: str, locale_id: typing.Optional[str] = None, - site_id: typing.Optional[str] = OMIT, title: typing.Optional[str] = OMIT, slug: typing.Optional[str] = OMIT, - parent_id: typing.Optional[str] = OMIT, - collection_id: typing.Optional[str] = OMIT, - created_on: typing.Optional[dt.datetime] = OMIT, - last_updated: typing.Optional[dt.datetime] = OMIT, - archived: typing.Optional[bool] = OMIT, - draft: typing.Optional[bool] = OMIT, - can_branch: typing.Optional[bool] = OMIT, - is_branch: typing.Optional[bool] = OMIT, - is_members_only: typing.Optional[bool] = OMIT, - seo: typing.Optional[PageSeo] = OMIT, - open_graph: typing.Optional[PageOpenGraph] = OMIT, - page_locale_id: typing.Optional[str] = OMIT, - published_path: typing.Optional[str] = OMIT, + seo: typing.Optional[PageMetadataWriteSeo] = OMIT, + open_graph: typing.Optional[PageMetadataWriteOpenGraph] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Page: """ @@ -304,60 +298,26 @@ def update_page_settings( page_id : str Unique identifier for a Page - id : str - Unique identifier for the Page - locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. - site_id : typing.Optional[str] - Unique identifier for the Site + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) title : typing.Optional[str] - Title of the Page + Title for the page slug : typing.Optional[str] - slug of the Page (derived from title) - - parent_id : typing.Optional[str] - Identifier of the parent folder - - collection_id : typing.Optional[str] - Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. - - created_on : typing.Optional[dt.datetime] - The date the Page was created - - last_updated : typing.Optional[dt.datetime] - The date the Page was most recently updated - - archived : typing.Optional[bool] - Whether the Page has been archived + Slug for the page. - draft : typing.Optional[bool] - Whether the Page is a draft - can_branch : typing.Optional[bool] - Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) + **Note:** Updating slugs in secondary locales is only supported in Advanced and Enterprise localization add-on plans. - is_branch : typing.Optional[bool] - Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) - - is_members_only : typing.Optional[bool] - Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) - - seo : typing.Optional[PageSeo] + seo : typing.Optional[PageMetadataWriteSeo] SEO-related fields for the Page - open_graph : typing.Optional[PageOpenGraph] + open_graph : typing.Optional[PageMetadataWriteOpenGraph] Open Graph fields for the Page - page_locale_id : typing.Optional[str] - Unique ID of the page locale - - published_path : typing.Optional[str] - Relative path of the published page URL - request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -368,9 +328,11 @@ def update_page_settings( Examples -------- - import datetime - - from webflow import PageOpenGraph, PageSeo, Webflow + from webflow import Webflow + from webflow.resources.pages import ( + PageMetadataWriteOpenGraph, + PageMetadataWriteSeo, + ) client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -378,60 +340,39 @@ def update_page_settings( client.pages.update_page_settings( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", title="Guide to the Galaxy", slug="guide-to-the-galaxy", - created_on=datetime.datetime.fromisoformat( - "2024-03-11 10:42:00+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2024-03-11 10:42:42+00:00", - ), - archived=False, - draft=False, - can_branch=True, - is_branch=False, - seo=PageSeo( + seo=PageMetadataWriteSeo( title="The Ultimate Hitchhiker's Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", ), - open_graph=PageOpenGraph( + open_graph=PageMetadataWriteOpenGraph( title="Explore the Cosmos with The Ultimate Guide", title_copied=False, description="Dive deep into the mysteries of the universe with your guide to everything galactic.", description_copied=False, ), - page_locale_id="653fd9af6a07fc9cfd7a5e57", - published_path="/en-us/guide-to-the-galaxy", ) """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, method="PUT", params={ "localeId": locale_id, }, json={ - "id": id, - "siteId": site_id, "title": title, "slug": slug, - "parentId": parent_id, - "collectionId": collection_id, - "createdOn": created_on, - "lastUpdated": last_updated, - "archived": archived, - "draft": draft, - "canBranch": can_branch, - "isBranch": is_branch, - "isMembersOnly": is_members_only, - "seo": convert_and_respect_annotation_metadata(object_=seo, annotation=PageSeo, direction="write"), + "seo": convert_and_respect_annotation_metadata( + object_=seo, annotation=PageMetadataWriteSeo, direction="write" + ), "openGraph": convert_and_respect_annotation_metadata( - object_=open_graph, annotation=PageOpenGraph, direction="write" + object_=open_graph, annotation=PageMetadataWriteOpenGraph, direction="write" ), - "localeId": locale_id, - "publishedPath": published_path, + }, + headers={ + "content-type": "application/json", }, request_options=request_options, omit=OMIT, @@ -505,15 +446,14 @@ def get_content( page_id: str, *, locale_id: typing.Optional[str] = None, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> Dom: """ - Get static content from a static page. This includes text nodes, image nodes and component instances. - To retrieve the contents of components in the page use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint. + Get text and component instance content from a static page. - If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + Localization Required scope | `pages:read` @@ -523,12 +463,14 @@ def get_content( Unique identifier for a Page locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. - limit : typing.Optional[float] + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -549,10 +491,13 @@ def get_content( client.pages.get_content( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", + limit=1, + offset=1, ) """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -647,8 +592,9 @@ def update_static_content( This endpoint updates content on a static page in **secondary locales**. It supports updating up to 1000 nodes in a single request. Before making updates: - 1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) endpoint to identify available content nodes and their types - 2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint + 1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) endpoint to identify available content nodes and their types. + 2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + 3. DOM elements may include a `data-w-id` attribute. This attribute is used by Webflow to maintain custom attributes and links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. This endpoint is specifically for localized pages. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. @@ -680,6 +626,10 @@ def update_static_content( from webflow import ( ComponentInstanceNodePropertyOverridesWrite, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + Select, + SelectNodeWriteChoicesItem, + SubmitButtonNodeWrite, + TextInputNodeWrite, TextNodeWrite, Webflow, ) @@ -699,6 +649,28 @@ def update_static_content( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Don't Panic!

Always know where your towel is.

", ), + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInputNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButtonNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), ComponentInstanceNodePropertyOverridesWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ @@ -717,6 +689,7 @@ def update_static_content( """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, @@ -817,8 +790,8 @@ async def list( site_id: str, *, locale_id: typing.Optional[str] = None, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> PageList: """ @@ -832,12 +805,14 @@ async def list( Unique identifier for a Site locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. - limit : typing.Optional[float] + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -863,6 +838,8 @@ async def main() -> None: await client.pages.list( site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0", + limit=1, + offset=1, ) @@ -870,6 +847,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/pages", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -960,7 +938,9 @@ async def get_metadata( Unique identifier for a Page locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -992,6 +972,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -1066,24 +1047,11 @@ async def update_page_settings( self, page_id: str, *, - id: str, locale_id: typing.Optional[str] = None, - site_id: typing.Optional[str] = OMIT, title: typing.Optional[str] = OMIT, slug: typing.Optional[str] = OMIT, - parent_id: typing.Optional[str] = OMIT, - collection_id: typing.Optional[str] = OMIT, - created_on: typing.Optional[dt.datetime] = OMIT, - last_updated: typing.Optional[dt.datetime] = OMIT, - archived: typing.Optional[bool] = OMIT, - draft: typing.Optional[bool] = OMIT, - can_branch: typing.Optional[bool] = OMIT, - is_branch: typing.Optional[bool] = OMIT, - is_members_only: typing.Optional[bool] = OMIT, - seo: typing.Optional[PageSeo] = OMIT, - open_graph: typing.Optional[PageOpenGraph] = OMIT, - page_locale_id: typing.Optional[str] = OMIT, - published_path: typing.Optional[str] = OMIT, + seo: typing.Optional[PageMetadataWriteSeo] = OMIT, + open_graph: typing.Optional[PageMetadataWriteOpenGraph] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Page: """ @@ -1096,60 +1064,26 @@ async def update_page_settings( page_id : str Unique identifier for a Page - id : str - Unique identifier for the Page - locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. - site_id : typing.Optional[str] - Unique identifier for the Site + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) title : typing.Optional[str] - Title of the Page + Title for the page slug : typing.Optional[str] - slug of the Page (derived from title) - - parent_id : typing.Optional[str] - Identifier of the parent folder - - collection_id : typing.Optional[str] - Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. - - created_on : typing.Optional[dt.datetime] - The date the Page was created - - last_updated : typing.Optional[dt.datetime] - The date the Page was most recently updated + Slug for the page. - archived : typing.Optional[bool] - Whether the Page has been archived - draft : typing.Optional[bool] - Whether the Page is a draft + **Note:** Updating slugs in secondary locales is only supported in Advanced and Enterprise localization add-on plans. - can_branch : typing.Optional[bool] - Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) - - is_branch : typing.Optional[bool] - Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) - - is_members_only : typing.Optional[bool] - Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) - - seo : typing.Optional[PageSeo] + seo : typing.Optional[PageMetadataWriteSeo] SEO-related fields for the Page - open_graph : typing.Optional[PageOpenGraph] + open_graph : typing.Optional[PageMetadataWriteOpenGraph] Open Graph fields for the Page - page_locale_id : typing.Optional[str] - Unique ID of the page locale - - published_path : typing.Optional[str] - Relative path of the published page URL - request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1161,9 +1095,12 @@ async def update_page_settings( Examples -------- import asyncio - import datetime - from webflow import AsyncWebflow, PageOpenGraph, PageSeo + from webflow import AsyncWebflow + from webflow.resources.pages import ( + PageMetadataWriteOpenGraph, + PageMetadataWriteSeo, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -1174,32 +1111,18 @@ async def main() -> None: await client.pages.update_page_settings( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", title="Guide to the Galaxy", slug="guide-to-the-galaxy", - created_on=datetime.datetime.fromisoformat( - "2024-03-11 10:42:00+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2024-03-11 10:42:42+00:00", - ), - archived=False, - draft=False, - can_branch=True, - is_branch=False, - seo=PageSeo( + seo=PageMetadataWriteSeo( title="The Ultimate Hitchhiker's Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", ), - open_graph=PageOpenGraph( + open_graph=PageMetadataWriteOpenGraph( title="Explore the Cosmos with The Ultimate Guide", title_copied=False, description="Dive deep into the mysteries of the universe with your guide to everything galactic.", description_copied=False, ), - page_locale_id="653fd9af6a07fc9cfd7a5e57", - published_path="/en-us/guide-to-the-galaxy", ) @@ -1207,30 +1130,23 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, method="PUT", params={ "localeId": locale_id, }, json={ - "id": id, - "siteId": site_id, "title": title, "slug": slug, - "parentId": parent_id, - "collectionId": collection_id, - "createdOn": created_on, - "lastUpdated": last_updated, - "archived": archived, - "draft": draft, - "canBranch": can_branch, - "isBranch": is_branch, - "isMembersOnly": is_members_only, - "seo": convert_and_respect_annotation_metadata(object_=seo, annotation=PageSeo, direction="write"), + "seo": convert_and_respect_annotation_metadata( + object_=seo, annotation=PageMetadataWriteSeo, direction="write" + ), "openGraph": convert_and_respect_annotation_metadata( - object_=open_graph, annotation=PageOpenGraph, direction="write" + object_=open_graph, annotation=PageMetadataWriteOpenGraph, direction="write" ), - "localeId": locale_id, - "publishedPath": published_path, + }, + headers={ + "content-type": "application/json", }, request_options=request_options, omit=OMIT, @@ -1304,15 +1220,14 @@ async def get_content( page_id: str, *, locale_id: typing.Optional[str] = None, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> Dom: """ - Get static content from a static page. This includes text nodes, image nodes and component instances. - To retrieve the contents of components in the page use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint. + Get text and component instance content from a static page. - If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + Localization Required scope | `pages:read` @@ -1322,12 +1237,14 @@ async def get_content( Unique identifier for a Page locale_id : typing.Optional[str] - Unique identifier for a specific locale. Applicable, when using localization. + Unique identifier for a specific Locale. - limit : typing.Optional[float] + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -1353,6 +1270,8 @@ async def main() -> None: await client.pages.get_content( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", + limit=1, + offset=1, ) @@ -1360,6 +1279,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "localeId": locale_id, @@ -1454,8 +1374,9 @@ async def update_static_content( This endpoint updates content on a static page in **secondary locales**. It supports updating up to 1000 nodes in a single request. Before making updates: - 1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) endpoint to identify available content nodes and their types - 2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint + 1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) endpoint to identify available content nodes and their types. + 2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + 3. DOM elements may include a `data-w-id` attribute. This attribute is used by Webflow to maintain custom attributes and links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. This endpoint is specifically for localized pages. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. @@ -1490,6 +1411,10 @@ async def update_static_content( AsyncWebflow, ComponentInstanceNodePropertyOverridesWrite, ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + Select, + SelectNodeWriteChoicesItem, + SubmitButtonNodeWrite, + TextInputNodeWrite, TextNodeWrite, ) @@ -1511,6 +1436,28 @@ async def main() -> None: node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Don't Panic!

Always know where your towel is.

", ), + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem( + value="choice-1", + text="First choice", + ), + SelectNodeWriteChoicesItem( + value="choice-2", + text="Second choice", + ), + ], + ), + TextInputNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", + placeholder="Enter something here...", + ), + SubmitButtonNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", + value="Submit", + waiting_text="Submitting...", + ), ComponentInstanceNodePropertyOverridesWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ @@ -1532,6 +1479,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, method="POST", params={ "localeId": locale_id, diff --git a/src/webflow/resources/pages/resources/scripts/client.py b/src/webflow/resources/pages/resources/scripts/client.py index 56bd39a..cd1086f 100644 --- a/src/webflow/resources/pages/resources/scripts/client.py +++ b/src/webflow/resources/pages/resources/scripts/client.py @@ -31,13 +31,7 @@ def get_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Page. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Get all scripts applied to a page. Required scope | `custom_code:read` @@ -67,6 +61,7 @@ def get_custom_code( """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -144,15 +139,11 @@ def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Page. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - A site can have a maximum of 800 registered scripts. + Apply registered scripts to a page. If you have multiple scripts your App needs to apply or maintain on a page, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a page, the script must first be registered to a Site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -204,6 +195,7 @@ def upsert_custom_code( """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="PUT", json={ "scripts": convert_and_respect_annotation_metadata( @@ -291,13 +283,11 @@ def upsert_custom_code( def delete_custom_code(self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete the custom code block that an app has created for a page + Remove all scripts from a page applied by the App. This endpoint will not remove scripts from the site's registered scripts. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-pages/upsert-custom-code) endpoint. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write` @@ -326,6 +316,7 @@ def delete_custom_code(self, page_id: str, *, request_options: typing.Optional[R """ _response = self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -396,13 +387,7 @@ async def get_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Page. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Get all scripts applied to a page. Required scope | `custom_code:read` @@ -440,6 +425,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -517,15 +503,11 @@ async def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Page. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - A site can have a maximum of 800 registered scripts. + Apply registered scripts to a page. If you have multiple scripts your App needs to apply or maintain on a page, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a page, the script must first be registered to a Site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -585,6 +567,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="PUT", json={ "scripts": convert_and_respect_annotation_metadata( @@ -674,13 +657,11 @@ async def delete_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> None: """ - Delete the custom code block that an app has created for a page + Remove all scripts from a page applied by the App. This endpoint will not remove scripts from the site's registered scripts. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-pages/upsert-custom-code) endpoint. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write` @@ -717,6 +698,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) diff --git a/src/webflow/resources/pages/types/__init__.py b/src/webflow/resources/pages/types/__init__.py index 08c0325..6e07bcf 100644 --- a/src/webflow/resources/pages/types/__init__.py +++ b/src/webflow/resources/pages/types/__init__.py @@ -1,6 +1,8 @@ # This file was auto-generated by Fern from our API Definition. from .page_dom_write_nodes_item import PageDomWriteNodesItem +from .page_metadata_write_open_graph import PageMetadataWriteOpenGraph +from .page_metadata_write_seo import PageMetadataWriteSeo from .update_static_content_response import UpdateStaticContentResponse -__all__ = ["PageDomWriteNodesItem", "UpdateStaticContentResponse"] +__all__ = ["PageDomWriteNodesItem", "PageMetadataWriteOpenGraph", "PageMetadataWriteSeo", "UpdateStaticContentResponse"] diff --git a/src/webflow/resources/pages/types/page_dom_write_nodes_item.py b/src/webflow/resources/pages/types/page_dom_write_nodes_item.py index 05d1f3f..7c616d9 100644 --- a/src/webflow/resources/pages/types/page_dom_write_nodes_item.py +++ b/src/webflow/resources/pages/types/page_dom_write_nodes_item.py @@ -3,5 +3,16 @@ import typing from ....types.text_node_write import TextNodeWrite from ....types.component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite +from ....types.select import Select +from ....types.text_input_node_write import TextInputNodeWrite +from ....types.submit_button_node_write import SubmitButtonNodeWrite +from ....types.search_button_node_write import SearchButtonNodeWrite -PageDomWriteNodesItem = typing.Union[TextNodeWrite, ComponentInstanceNodePropertyOverridesWrite] +PageDomWriteNodesItem = typing.Union[ + TextNodeWrite, + ComponentInstanceNodePropertyOverridesWrite, + Select, + TextInputNodeWrite, + SubmitButtonNodeWrite, + SearchButtonNodeWrite, +] diff --git a/src/webflow/resources/pages/types/page_metadata_write_open_graph.py b/src/webflow/resources/pages/types/page_metadata_write_open_graph.py new file mode 100644 index 0000000..7b6a099 --- /dev/null +++ b/src/webflow/resources/pages/types/page_metadata_write_open_graph.py @@ -0,0 +1,47 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ....core.serialization import FieldMetadata +from ....core.pydantic_utilities import IS_PYDANTIC_V2 + + +class PageMetadataWriteOpenGraph(UniversalBaseModel): + """ + Open Graph fields for the Page + """ + + title: typing.Optional[str] = pydantic.Field(default=None) + """ + The title supplied to Open Graph annotations + """ + + title_copied: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="titleCopied")] = ( + pydantic.Field(default=None) + ) + """ + Indicates the Open Graph title was copied from the SEO title + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + The description supplied to Open Graph annotations + """ + + description_copied: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="descriptionCopied")] = ( + pydantic.Field(default=None) + ) + """ + Indicates the Open Graph description was copied from the SEO description + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/pages/types/page_metadata_write_seo.py b/src/webflow/resources/pages/types/page_metadata_write_seo.py new file mode 100644 index 0000000..1b339a0 --- /dev/null +++ b/src/webflow/resources/pages/types/page_metadata_write_seo.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2 + + +class PageMetadataWriteSeo(UniversalBaseModel): + """ + SEO-related fields for the Page + """ + + title: typing.Optional[str] = pydantic.Field(default=None) + """ + The Page title shown in search engine results + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + The Page description shown in search engine results + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/products/__init__.py b/src/webflow/resources/products/__init__.py index 9fced2c..adf933b 100644 --- a/src/webflow/resources/products/__init__.py +++ b/src/webflow/resources/products/__init__.py @@ -1,5 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .types import ProductsCreateSkuResponse +from .types import ProductSkuCreateProduct, ProductSkuCreateSku, ProductsCreateSkuResponse -__all__ = ["ProductsCreateSkuResponse"] +__all__ = ["ProductSkuCreateProduct", "ProductSkuCreateSku", "ProductsCreateSkuResponse"] diff --git a/src/webflow/resources/products/client.py b/src/webflow/resources/products/client.py index c856fef..5850318 100644 --- a/src/webflow/resources/products/client.py +++ b/src/webflow/resources/products/client.py @@ -16,11 +16,13 @@ from ...errors.internal_server_error import InternalServerError from json.decoder import JSONDecodeError from ...core.api_error import ApiError +from .types.product_sku_create_product import ProductSkuCreateProduct +from .types.product_sku_create_sku import ProductSkuCreateSku from ...types.publish_status import PublishStatus -from ...types.product import Product -from ...types.sku import Sku from ...types.product_and_sk_us import ProductAndSkUs from ...core.serialization import convert_and_respect_annotation_metadata +from ...types.product import Product +from ...types.sku import Sku from .types.products_create_sku_response import ProductsCreateSkuResponse from ...core.client_wrapper import AsyncClientWrapper @@ -36,8 +38,8 @@ def list( self, site_id: str, *, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUsList: """ @@ -53,10 +55,10 @@ def list( site_id : str Unique identifier for a Site - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) request_options : typing.Optional[RequestOptions] @@ -76,10 +78,13 @@ def list( ) client.products.list( site_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -175,22 +180,18 @@ def create( self, site_id: str, *, + product: ProductSkuCreateProduct, + sku: ProductSkuCreateSku, publish_status: typing.Optional[PublishStatus] = OMIT, - product: typing.Optional[Product] = OMIT, - sku: typing.Optional[Sku] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUs: """ - Create a new product and SKU. - - When you create a product, you will always create a SKU, since a Product Item must have, at minimum, a single SKU. + Create a new ecommerce product and defaultSKU. A product, at minimum, must have a single SKU. - To create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large: - - Create parameters in `sku-properties`, also known as [product options and variants.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). - - A single `sku-property` would be `color`. Within the `color` property, list the various colors of T-shirts as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. - - Once, you've created a Product and its `sku-properties` with `enum` values, Webflow will create a **default SKU**, which will automatically be a combination of the first `sku-properties` you've created. - - In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. - - After you've created your product, you can create additional SKUs using the [Create SKU endpoint.](/data/reference/ecommerce/products/create-sku) + To create a product with multiple SKUs: + - First, create a list of `sku-properties`, also known as [product options](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). For example, a T-shirt product may have a "color" `sku-property`, with a list of enum values: red, yellow, and blue, another `sku-property` may be "size", with a list of enum values: small, medium, and large. + - Once, a product is created with a list of `sku-properties`, Webflow will create a **default SKU**, which is always a combination of the first `enum` values of each `sku-property`. (e.g. Small - Red - T-Shirt) + - After creation, you can create additional SKUs for the product, using the [Create SKUs endpoint.](/data/reference/ecommerce/products/create-sku) Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. @@ -201,11 +202,11 @@ def create( site_id : str Unique identifier for a Site - publish_status : typing.Optional[PublishStatus] + product : ProductSkuCreateProduct - product : typing.Optional[Product] + sku : ProductSkuCreateSku - sku : typing.Optional[Sku] + publish_status : typing.Optional[PublishStatus] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -217,24 +218,102 @@ def create( Examples -------- - from webflow import Webflow + from webflow import ( + ProductFieldData, + SkuFieldData, + SkuFieldDataPrice, + SkuPropertyList, + SkuPropertyListEnumItem, + Webflow, + ) + from webflow.resources.products import ( + ProductSkuCreateProduct, + ProductSkuCreateSku, + ) client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) client.products.create( site_id="580e63e98c9a982ac9b8b741", + publish_status="staging", + product=ProductSkuCreateProduct( + field_data=ProductFieldData( + name="Colorful T-shirt", + slug="colorful-t-shirt", + description="Our best-selling t-shirt available in multiple colors and sizes", + sku_properties=[ + SkuPropertyList( + id="color", + name="Color", + enum=[ + SkuPropertyListEnumItem( + id="red", + name="Red", + slug="red", + ), + SkuPropertyListEnumItem( + id="yellow", + name="Yellow", + slug="yellow", + ), + SkuPropertyListEnumItem( + id="blue", + name="Blue", + slug="blue", + ), + ], + ), + SkuPropertyList( + id="size", + name="Size", + enum=[ + SkuPropertyListEnumItem( + id="small", + name="Small", + slug="small", + ), + SkuPropertyListEnumItem( + id="medium", + name="Medium", + slug="medium", + ), + SkuPropertyListEnumItem( + id="large", + name="Large", + slug="large", + ), + ], + ), + ], + ), + ), + sku=ProductSkuCreateSku( + field_data=SkuFieldData( + name="Colorful T-shirt - Red Small", + slug="colorful-t-shirt-red-small", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", + ), + ), ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "publishStatus": publish_status, "product": convert_and_respect_annotation_metadata( - object_=product, annotation=Product, direction="write" + object_=product, annotation=ProductSkuCreateProduct, direction="write" + ), + "sku": convert_and_respect_annotation_metadata( + object_=sku, annotation=ProductSkuCreateSku, direction="write" ), - "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), }, headers={ "content-type": "application/json", @@ -365,6 +444,7 @@ def get( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -505,6 +585,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "publishStatus": publish_status, @@ -642,7 +723,9 @@ def create_sku( Examples -------- - from webflow import Sku, Webflow + import datetime + + from webflow import Sku, SkuFieldData, SkuFieldDataPrice, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -650,11 +733,35 @@ def create_sku( client.products.create_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", - skus=[Sku()], + skus=[ + Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ) + ], ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "publishStatus": publish_status, @@ -794,7 +901,9 @@ def update_sku( Examples -------- - from webflow import Sku, Webflow + import datetime + + from webflow import Sku, SkuFieldData, SkuFieldDataPrice, Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", @@ -803,11 +912,33 @@ def update_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", sku_id="5e8518516e147040726cc415", - sku=Sku(), + sku=Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ), ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "publishStatus": publish_status, @@ -912,8 +1043,8 @@ async def list( self, site_id: str, *, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUsList: """ @@ -929,10 +1060,10 @@ async def list( site_id : str Unique identifier for a Site - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) request_options : typing.Optional[RequestOptions] @@ -957,6 +1088,8 @@ async def list( async def main() -> None: await client.products.list( site_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) @@ -964,6 +1097,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -1059,22 +1193,18 @@ async def create( self, site_id: str, *, + product: ProductSkuCreateProduct, + sku: ProductSkuCreateSku, publish_status: typing.Optional[PublishStatus] = OMIT, - product: typing.Optional[Product] = OMIT, - sku: typing.Optional[Sku] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> ProductAndSkUs: """ - Create a new product and SKU. + Create a new ecommerce product and defaultSKU. A product, at minimum, must have a single SKU. - When you create a product, you will always create a SKU, since a Product Item must have, at minimum, a single SKU. - - To create a Product with multiple SKUs - for example a T-shirt in sizes small, medium and large: - - Create parameters in `sku-properties`, also known as [product options and variants.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). - - A single `sku-property` would be `color`. Within the `color` property, list the various colors of T-shirts as an array of `enum` values: `royal-blue`, `crimson-red`, and `forrest-green`. - - Once, you've created a Product and its `sku-properties` with `enum` values, Webflow will create a **default SKU**, which will automatically be a combination of the first `sku-properties` you've created. - - In our example, the default SKU will be a Royal Blue T-Shirt, because our first `enum` of our Color `sku-property` is Royal Blue. - - After you've created your product, you can create additional SKUs using the [Create SKU endpoint.](/data/reference/ecommerce/products/create-sku) + To create a product with multiple SKUs: + - First, create a list of `sku-properties`, also known as [product options](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). For example, a T-shirt product may have a "color" `sku-property`, with a list of enum values: red, yellow, and blue, another `sku-property` may be "size", with a list of enum values: small, medium, and large. + - Once, a product is created with a list of `sku-properties`, Webflow will create a **default SKU**, which is always a combination of the first `enum` values of each `sku-property`. (e.g. Small - Red - T-Shirt) + - After creation, you can create additional SKUs for the product, using the [Create SKUs endpoint.](/data/reference/ecommerce/products/create-sku) Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. @@ -1085,11 +1215,11 @@ async def create( site_id : str Unique identifier for a Site - publish_status : typing.Optional[PublishStatus] + product : ProductSkuCreateProduct - product : typing.Optional[Product] + sku : ProductSkuCreateSku - sku : typing.Optional[Sku] + publish_status : typing.Optional[PublishStatus] request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -1103,7 +1233,18 @@ async def create( -------- import asyncio - from webflow import AsyncWebflow + from webflow import ( + AsyncWebflow, + ProductFieldData, + SkuFieldData, + SkuFieldDataPrice, + SkuPropertyList, + SkuPropertyListEnumItem, + ) + from webflow.resources.products import ( + ProductSkuCreateProduct, + ProductSkuCreateSku, + ) client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -1113,6 +1254,70 @@ async def create( async def main() -> None: await client.products.create( site_id="580e63e98c9a982ac9b8b741", + publish_status="staging", + product=ProductSkuCreateProduct( + field_data=ProductFieldData( + name="Colorful T-shirt", + slug="colorful-t-shirt", + description="Our best-selling t-shirt available in multiple colors and sizes", + sku_properties=[ + SkuPropertyList( + id="color", + name="Color", + enum=[ + SkuPropertyListEnumItem( + id="red", + name="Red", + slug="red", + ), + SkuPropertyListEnumItem( + id="yellow", + name="Yellow", + slug="yellow", + ), + SkuPropertyListEnumItem( + id="blue", + name="Blue", + slug="blue", + ), + ], + ), + SkuPropertyList( + id="size", + name="Size", + enum=[ + SkuPropertyListEnumItem( + id="small", + name="Small", + slug="small", + ), + SkuPropertyListEnumItem( + id="medium", + name="Medium", + slug="medium", + ), + SkuPropertyListEnumItem( + id="large", + name="Large", + slug="large", + ), + ], + ), + ], + ), + ), + sku=ProductSkuCreateSku( + field_data=SkuFieldData( + name="Colorful T-shirt - Red Small", + slug="colorful-t-shirt-red-small", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", + ), + ), ) @@ -1120,13 +1325,16 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "publishStatus": publish_status, "product": convert_and_respect_annotation_metadata( - object_=product, annotation=Product, direction="write" + object_=product, annotation=ProductSkuCreateProduct, direction="write" + ), + "sku": convert_and_respect_annotation_metadata( + object_=sku, annotation=ProductSkuCreateSku, direction="write" ), - "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), }, headers={ "content-type": "application/json", @@ -1265,6 +1473,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1413,6 +1622,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "publishStatus": publish_status, @@ -1551,8 +1761,9 @@ async def create_sku( Examples -------- import asyncio + import datetime - from webflow import AsyncWebflow, Sku + from webflow import AsyncWebflow, Sku, SkuFieldData, SkuFieldDataPrice client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -1563,7 +1774,30 @@ async def main() -> None: await client.products.create_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", - skus=[Sku()], + skus=[ + Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ) + ], ) @@ -1571,6 +1805,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "publishStatus": publish_status, @@ -1711,8 +1946,9 @@ async def update_sku( Examples -------- import asyncio + import datetime - from webflow import AsyncWebflow, Sku + from webflow import AsyncWebflow, Sku, SkuFieldData, SkuFieldDataPrice client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -1724,7 +1960,28 @@ async def main() -> None: site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", sku_id="5e8518516e147040726cc415", - sku=Sku(), + sku=Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + last_updated=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + created_on=datetime.datetime.fromisoformat( + "2023-03-17 18:47:35+00:00", + ), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice( + value=2499.0, + unit="USD", + currency="USD", + ), + ), + ), ) @@ -1732,6 +1989,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "publishStatus": publish_status, diff --git a/src/webflow/resources/products/types/__init__.py b/src/webflow/resources/products/types/__init__.py index b078afe..5b6d9b4 100644 --- a/src/webflow/resources/products/types/__init__.py +++ b/src/webflow/resources/products/types/__init__.py @@ -1,5 +1,7 @@ # This file was auto-generated by Fern from our API Definition. +from .product_sku_create_product import ProductSkuCreateProduct +from .product_sku_create_sku import ProductSkuCreateSku from .products_create_sku_response import ProductsCreateSkuResponse -__all__ = ["ProductsCreateSkuResponse"] +__all__ = ["ProductSkuCreateProduct", "ProductSkuCreateSku", "ProductsCreateSkuResponse"] diff --git a/src/webflow/resources/products/types/product_sku_create_product.py b/src/webflow/resources/products/types/product_sku_create_product.py new file mode 100644 index 0000000..750e5f4 --- /dev/null +++ b/src/webflow/resources/products/types/product_sku_create_product.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....types.product_field_data import ProductFieldData +from ....core.serialization import FieldMetadata +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ProductSkuCreateProduct(UniversalBaseModel): + field_data: typing_extensions.Annotated[typing.Optional[ProductFieldData], FieldMetadata(alias="fieldData")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/products/types/product_sku_create_sku.py b/src/webflow/resources/products/types/product_sku_create_sku.py new file mode 100644 index 0000000..2762a9a --- /dev/null +++ b/src/webflow/resources/products/types/product_sku_create_sku.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ....core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ....types.sku_field_data import SkuFieldData +from ....core.serialization import FieldMetadata +from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class ProductSkuCreateSku(UniversalBaseModel): + field_data: typing_extensions.Annotated[typing.Optional[SkuFieldData], FieldMetadata(alias="fieldData")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/products/types/products_create_sku_response.py b/src/webflow/resources/products/types/products_create_sku_response.py index e694930..cd68c3d 100644 --- a/src/webflow/resources/products/types/products_create_sku_response.py +++ b/src/webflow/resources/products/types/products_create_sku_response.py @@ -8,7 +8,7 @@ class ProductsCreateSkuResponse(UniversalBaseModel): - skus: typing.Optional[typing.List[Sku]] = None + skus: typing.List[Sku] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/resources/scripts/client.py b/src/webflow/resources/scripts/client.py index e9112fb..80026d9 100644 --- a/src/webflow/resources/scripts/client.py +++ b/src/webflow/resources/scripts/client.py @@ -28,14 +28,11 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> RegisteredScriptList: """ - List of scripts registered to a Site. + Get a list of scripts that have been registered to a site. A site can have a maximum of 800 registered scripts. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - Additionally, Scripts can be remotely hosted, or registered as inline snippets. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -65,6 +62,7 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -144,14 +142,11 @@ def register_hosted( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeHostedResponse: """ - Add a script to a Site's Custom Code registry. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - Additionally, Scripts can be remotely hosted, or registered as inline snippets. + Register a hosted script to a site. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -200,6 +195,7 @@ def register_hosted( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "hostedLocation": hosted_location, @@ -290,13 +286,11 @@ def register_inline( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeInlineResponse: """ - Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. + Register an inline script to a site. Inline scripts are limited to 2000 characters. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -344,6 +338,7 @@ def register_inline( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "sourceCode": source_code, @@ -431,14 +426,11 @@ async def list( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> RegisteredScriptList: """ - List of scripts registered to a Site. + Get a list of scripts that have been registered to a site. A site can have a maximum of 800 registered scripts. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - Additionally, Scripts can be remotely hosted, or registered as inline snippets. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -476,6 +468,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -555,14 +548,11 @@ async def register_hosted( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeHostedResponse: """ - Add a script to a Site's Custom Code registry. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - Additionally, Scripts can be remotely hosted, or registered as inline snippets. + Register a hosted script to a site. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -619,6 +609,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "hostedLocation": hosted_location, @@ -709,13 +700,11 @@ async def register_inline( request_options: typing.Optional[RequestOptions] = None, ) -> CustomCodeInlineResponse: """ - Add a script to a Site's Custom Code registry. Inline scripts can be between 1 and 2000 characters. - - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. + Register an inline script to a site. Inline scripts are limited to 2000 characters. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -771,6 +760,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "sourceCode": source_code, diff --git a/src/webflow/resources/sites/__init__.py b/src/webflow/resources/sites/__init__.py index 3ec19db..c070ab2 100644 --- a/src/webflow/resources/sites/__init__.py +++ b/src/webflow/resources/sites/__init__.py @@ -1,6 +1,39 @@ # This file was auto-generated by Fern from our API Definition. from .types import SitesPublishResponse -from .resources import activity_logs, plans, redirects, scripts +from .resources import ( + CommentsGetCommentThreadRequestSortBy, + CommentsGetCommentThreadRequestSortOrder, + CommentsListCommentRepliesRequestSortBy, + CommentsListCommentRepliesRequestSortOrder, + CommentsListCommentThreadsRequestSortBy, + CommentsListCommentThreadsRequestSortOrder, + WellKnownFileContentType, + activity_logs, + comments, + forms, + plans, + redirects, + robots_txt, + scripts, + well_known, +) -__all__ = ["SitesPublishResponse", "activity_logs", "plans", "redirects", "scripts"] +__all__ = [ + "CommentsGetCommentThreadRequestSortBy", + "CommentsGetCommentThreadRequestSortOrder", + "CommentsListCommentRepliesRequestSortBy", + "CommentsListCommentRepliesRequestSortOrder", + "CommentsListCommentThreadsRequestSortBy", + "CommentsListCommentThreadsRequestSortOrder", + "SitesPublishResponse", + "WellKnownFileContentType", + "activity_logs", + "comments", + "forms", + "plans", + "redirects", + "robots_txt", + "scripts", + "well_known", +] diff --git a/src/webflow/resources/sites/client.py b/src/webflow/resources/sites/client.py index c2a4468..84b91bd 100644 --- a/src/webflow/resources/sites/client.py +++ b/src/webflow/resources/sites/client.py @@ -4,8 +4,12 @@ from ...core.client_wrapper import SyncClientWrapper from .resources.redirects.client import RedirectsClient from .resources.plans.client import PlansClient +from .resources.robots_txt.client import RobotsTxtClient +from .resources.well_known.client import WellKnownClient from .resources.activity_logs.client import ActivityLogsClient +from .resources.comments.client import CommentsClient from .resources.scripts.client import ScriptsClient +from .resources.forms.client import FormsClient from ...core.request_options import RequestOptions from ...types.site import Site from ...core.jsonable_encoder import jsonable_encoder @@ -25,8 +29,12 @@ from ...core.client_wrapper import AsyncClientWrapper from .resources.redirects.client import AsyncRedirectsClient from .resources.plans.client import AsyncPlansClient +from .resources.robots_txt.client import AsyncRobotsTxtClient +from .resources.well_known.client import AsyncWellKnownClient from .resources.activity_logs.client import AsyncActivityLogsClient +from .resources.comments.client import AsyncCommentsClient from .resources.scripts.client import AsyncScriptsClient +from .resources.forms.client import AsyncFormsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -37,8 +45,12 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper self.redirects = RedirectsClient(client_wrapper=self._client_wrapper) self.plans = PlansClient(client_wrapper=self._client_wrapper) + self.robots_txt = RobotsTxtClient(client_wrapper=self._client_wrapper) + self.well_known = WellKnownClient(client_wrapper=self._client_wrapper) self.activity_logs = ActivityLogsClient(client_wrapper=self._client_wrapper) + self.comments = CommentsClient(client_wrapper=self._client_wrapper) self.scripts = ScriptsClient(client_wrapper=self._client_wrapper) + self.forms = FormsClient(client_wrapper=self._client_wrapper) def create( self, @@ -50,7 +62,9 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> Site: """ - Create a site. This endpoint requires an Enterprise workspace. + Create a site. + + This endpoint requires an Enterprise workspace. Required scope | `workspace:write` @@ -90,6 +104,7 @@ def create( """ _response = self._client_wrapper.httpx_client.request( f"workspaces/{jsonable_encoder(workspace_id)}/sites", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "name": name, @@ -203,6 +218,7 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Si """ _response = self._client_wrapper.httpx_client.request( "sites", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -282,6 +298,7 @@ def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -351,7 +368,9 @@ def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] def delete(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete a site. This endpoint requires an Enterprise workspace. + Delete a site. + + This endpoint requires an Enterprise workspace. Required scope | `sites:write` @@ -380,6 +399,7 @@ def delete(self, site_id: str, *, request_options: typing.Optional[RequestOption """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -460,7 +480,9 @@ def update( request_options: typing.Optional[RequestOptions] = None, ) -> Site: """ - Update a site. This endpoint requires an Enterprise workspace. + Update a site. + + This endpoint requires an Enterprise workspace. Required scope | `sites:write` @@ -496,6 +518,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "name": name, @@ -613,6 +636,7 @@ def get_custom_domain(self, site_id: str, *, request_options: typing.Optional[Re """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_domains", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -691,7 +715,9 @@ def publish( """ Publishes a site to one or more more domains. - This endpoint has a limit of one successful publish queue per minute. + To publish to a specific custom domain, use the domain IDs from the [Get Custom Domains](/data/reference/sites/get-custom-domain) endpoint. + + This endpoint has a specific rate limit of one successful publish queue per minute. Required scope | `sites:write` @@ -723,10 +749,13 @@ def publish( ) client.sites.publish( site_id="580e63e98c9a982ac9b8b741", + custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], + publish_to_webflow_subdomain=False, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/publish", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "customDomains": custom_domains, @@ -808,8 +837,12 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper self.redirects = AsyncRedirectsClient(client_wrapper=self._client_wrapper) self.plans = AsyncPlansClient(client_wrapper=self._client_wrapper) + self.robots_txt = AsyncRobotsTxtClient(client_wrapper=self._client_wrapper) + self.well_known = AsyncWellKnownClient(client_wrapper=self._client_wrapper) self.activity_logs = AsyncActivityLogsClient(client_wrapper=self._client_wrapper) + self.comments = AsyncCommentsClient(client_wrapper=self._client_wrapper) self.scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) + self.forms = AsyncFormsClient(client_wrapper=self._client_wrapper) async def create( self, @@ -821,7 +854,9 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> Site: """ - Create a site. This endpoint requires an Enterprise workspace. + Create a site. + + This endpoint requires an Enterprise workspace. Required scope | `workspace:write` @@ -869,6 +904,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"workspaces/{jsonable_encoder(workspace_id)}/sites", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "name": name, @@ -990,6 +1026,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( "sites", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1077,6 +1114,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1146,7 +1184,9 @@ async def main() -> None: async def delete(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete a site. This endpoint requires an Enterprise workspace. + Delete a site. + + This endpoint requires an Enterprise workspace. Required scope | `sites:write` @@ -1183,6 +1223,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -1263,7 +1304,9 @@ async def update( request_options: typing.Optional[RequestOptions] = None, ) -> Site: """ - Update a site. This endpoint requires an Enterprise workspace. + Update a site. + + This endpoint requires an Enterprise workspace. Required scope | `sites:write` @@ -1307,6 +1350,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "name": name, @@ -1434,6 +1478,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_domains", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -1512,7 +1557,9 @@ async def publish( """ Publishes a site to one or more more domains. - This endpoint has a limit of one successful publish queue per minute. + To publish to a specific custom domain, use the domain IDs from the [Get Custom Domains](/data/reference/sites/get-custom-domain) endpoint. + + This endpoint has a specific rate limit of one successful publish queue per minute. Required scope | `sites:write` @@ -1549,6 +1596,8 @@ async def publish( async def main() -> None: await client.sites.publish( site_id="580e63e98c9a982ac9b8b741", + custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], + publish_to_webflow_subdomain=False, ) @@ -1556,6 +1605,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/publish", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "customDomains": custom_domains, diff --git a/src/webflow/resources/sites/resources/__init__.py b/src/webflow/resources/sites/resources/__init__.py index 1197a83..578d8dc 100644 --- a/src/webflow/resources/sites/resources/__init__.py +++ b/src/webflow/resources/sites/resources/__init__.py @@ -1,5 +1,30 @@ # This file was auto-generated by Fern from our API Definition. -from . import activity_logs, plans, redirects, scripts +from . import activity_logs, comments, forms, plans, redirects, robots_txt, scripts, well_known +from .comments import ( + CommentsGetCommentThreadRequestSortBy, + CommentsGetCommentThreadRequestSortOrder, + CommentsListCommentRepliesRequestSortBy, + CommentsListCommentRepliesRequestSortOrder, + CommentsListCommentThreadsRequestSortBy, + CommentsListCommentThreadsRequestSortOrder, +) +from .well_known import WellKnownFileContentType -__all__ = ["activity_logs", "plans", "redirects", "scripts"] +__all__ = [ + "CommentsGetCommentThreadRequestSortBy", + "CommentsGetCommentThreadRequestSortOrder", + "CommentsListCommentRepliesRequestSortBy", + "CommentsListCommentRepliesRequestSortOrder", + "CommentsListCommentThreadsRequestSortBy", + "CommentsListCommentThreadsRequestSortOrder", + "WellKnownFileContentType", + "activity_logs", + "comments", + "forms", + "plans", + "redirects", + "robots_txt", + "scripts", + "well_known", +] diff --git a/src/webflow/resources/sites/resources/activity_logs/client.py b/src/webflow/resources/sites/resources/activity_logs/client.py index cf4e1b3..d36303b 100644 --- a/src/webflow/resources/sites/resources/activity_logs/client.py +++ b/src/webflow/resources/sites/resources/activity_logs/client.py @@ -24,22 +24,26 @@ def list( self, site_id: str, *, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SiteActivityLogResponse: """ - Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` + Retrieve Activity Logs for a specific Site. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_activity:read` Parameters ---------- site_id : str Unique identifier for a Site - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -59,10 +63,13 @@ def list( ) client.sites.activity_logs.list( site_id="580e63e98c9a982ac9b8b741", + limit=1, + offset=1, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/activity_logs", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "limit": limit, @@ -133,22 +140,26 @@ async def list( self, site_id: str, *, - limit: typing.Optional[float] = None, - offset: typing.Optional[float] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SiteActivityLogResponse: """ - Retrieve Activity Logs for a specific Site. Requires Site to be on an Enterprise plan.

Required scope | `site_activity:read` + Retrieve Activity Logs for a specific Site. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_activity:read` Parameters ---------- site_id : str Unique identifier for a Site - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records request_options : typing.Optional[RequestOptions] @@ -173,6 +184,8 @@ async def list( async def main() -> None: await client.sites.activity_logs.list( site_id="580e63e98c9a982ac9b8b741", + limit=1, + offset=1, ) @@ -180,6 +193,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/activity_logs", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "limit": limit, diff --git a/src/webflow/resources/sites/resources/comments/__init__.py b/src/webflow/resources/sites/resources/comments/__init__.py new file mode 100644 index 0000000..1bf96a0 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/__init__.py @@ -0,0 +1,19 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import ( + CommentsGetCommentThreadRequestSortBy, + CommentsGetCommentThreadRequestSortOrder, + CommentsListCommentRepliesRequestSortBy, + CommentsListCommentRepliesRequestSortOrder, + CommentsListCommentThreadsRequestSortBy, + CommentsListCommentThreadsRequestSortOrder, +) + +__all__ = [ + "CommentsGetCommentThreadRequestSortBy", + "CommentsGetCommentThreadRequestSortOrder", + "CommentsListCommentRepliesRequestSortBy", + "CommentsListCommentRepliesRequestSortOrder", + "CommentsListCommentThreadsRequestSortBy", + "CommentsListCommentThreadsRequestSortOrder", +] diff --git a/src/webflow/resources/sites/resources/comments/client.py b/src/webflow/resources/sites/resources/comments/client.py new file mode 100644 index 0000000..748e6e5 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/client.py @@ -0,0 +1,937 @@ +# This file was auto-generated by Fern from our API Definition. + +from .....core.client_wrapper import SyncClientWrapper +import typing +from .types.comments_list_comment_threads_request_sort_by import CommentsListCommentThreadsRequestSortBy +from .types.comments_list_comment_threads_request_sort_order import CommentsListCommentThreadsRequestSortOrder +from .....core.request_options import RequestOptions +from .....types.comment_thread_list import CommentThreadList +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as +from .....errors.bad_request_error import BadRequestError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .types.comments_get_comment_thread_request_sort_by import CommentsGetCommentThreadRequestSortBy +from .types.comments_get_comment_thread_request_sort_order import CommentsGetCommentThreadRequestSortOrder +from .....types.comment_thread import CommentThread +from .types.comments_list_comment_replies_request_sort_by import CommentsListCommentRepliesRequestSortBy +from .types.comments_list_comment_replies_request_sort_order import CommentsListCommentRepliesRequestSortOrder +from .....types.comment_reply_list import CommentReplyList +from .....core.client_wrapper import AsyncClientWrapper + + +class CommentsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list_comment_threads( + self, + site_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsListCommentThreadsRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentThreadsRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentThreadList: + """ + List all comment threads for a site. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentThreadsRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentThreadsRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentThreadList + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.comments.list_comment_threads( + site_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentThreadList, + parse_obj_as( + type_=CommentThreadList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def get_comment_thread( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsGetCommentThreadRequestSortBy] = None, + sort_order: typing.Optional[CommentsGetCommentThreadRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentThread: + """ + Get details of a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsGetCommentThreadRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsGetCommentThreadRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentThread + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.comments.get_comment_thread( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentThread, + parse_obj_as( + type_=CommentThread, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def list_comment_replies( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsListCommentRepliesRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentRepliesRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentReplyList: + """ + List all replies to a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentRepliesRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentRepliesRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentReplyList + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.comments.list_comment_replies( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}/replies", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentReplyList, + parse_obj_as( + type_=CommentReplyList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncCommentsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list_comment_threads( + self, + site_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsListCommentThreadsRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentThreadsRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentThreadList: + """ + List all comment threads for a site. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentThreadsRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentThreadsRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentThreadList + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.comments.list_comment_threads( + site_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentThreadList, + parse_obj_as( + type_=CommentThreadList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def get_comment_thread( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsGetCommentThreadRequestSortBy] = None, + sort_order: typing.Optional[CommentsGetCommentThreadRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentThread: + """ + Get details of a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsGetCommentThreadRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsGetCommentThreadRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentThread + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.comments.get_comment_thread( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentThread, + parse_obj_as( + type_=CommentThread, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def list_comment_replies( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsListCommentRepliesRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentRepliesRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> CommentReplyList: + """ + List all replies to a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentRepliesRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentRepliesRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CommentReplyList + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.comments.list_comment_replies( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}/replies", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + CommentReplyList, + parse_obj_as( + type_=CommentReplyList, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/webflow/resources/sites/resources/comments/types/__init__.py b/src/webflow/resources/sites/resources/comments/types/__init__.py new file mode 100644 index 0000000..380d194 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/__init__.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +from .comments_get_comment_thread_request_sort_by import CommentsGetCommentThreadRequestSortBy +from .comments_get_comment_thread_request_sort_order import CommentsGetCommentThreadRequestSortOrder +from .comments_list_comment_replies_request_sort_by import CommentsListCommentRepliesRequestSortBy +from .comments_list_comment_replies_request_sort_order import CommentsListCommentRepliesRequestSortOrder +from .comments_list_comment_threads_request_sort_by import CommentsListCommentThreadsRequestSortBy +from .comments_list_comment_threads_request_sort_order import CommentsListCommentThreadsRequestSortOrder + +__all__ = [ + "CommentsGetCommentThreadRequestSortBy", + "CommentsGetCommentThreadRequestSortOrder", + "CommentsListCommentRepliesRequestSortBy", + "CommentsListCommentRepliesRequestSortOrder", + "CommentsListCommentThreadsRequestSortBy", + "CommentsListCommentThreadsRequestSortOrder", +] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_by.py b/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_by.py new file mode 100644 index 0000000..14daabb --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_by.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsGetCommentThreadRequestSortBy = typing.Union[typing.Literal["createdOn", "lastUpdated"], typing.Any] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_order.py b/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_order.py new file mode 100644 index 0000000..3da3ffc --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_get_comment_thread_request_sort_order.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsGetCommentThreadRequestSortOrder = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_by.py b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_by.py new file mode 100644 index 0000000..67fcb98 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_by.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsListCommentRepliesRequestSortBy = typing.Union[typing.Literal["createdOn", "lastUpdated"], typing.Any] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_order.py b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_order.py new file mode 100644 index 0000000..03c42c3 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_replies_request_sort_order.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsListCommentRepliesRequestSortOrder = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_by.py b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_by.py new file mode 100644 index 0000000..1d541ce --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_by.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsListCommentThreadsRequestSortBy = typing.Union[typing.Literal["createdOn", "lastUpdated"], typing.Any] diff --git a/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_order.py b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_order.py new file mode 100644 index 0000000..d2c2606 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/types/comments_list_comment_threads_request_sort_order.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CommentsListCommentThreadsRequestSortOrder = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/webflow/types/user_limit_reached.py b/src/webflow/resources/sites/resources/forms/__init__.py similarity index 51% rename from src/webflow/types/user_limit_reached.py rename to src/webflow/resources/sites/resources/forms/__init__.py index 7f149c2..f3ea265 100644 --- a/src/webflow/types/user_limit_reached.py +++ b/src/webflow/resources/sites/resources/forms/__init__.py @@ -1,5 +1,2 @@ # This file was auto-generated by Fern from our API Definition. -import typing - -UserLimitReached = typing.Optional[typing.Any] diff --git a/src/webflow/resources/users/client.py b/src/webflow/resources/sites/resources/forms/client.py similarity index 74% rename from src/webflow/resources/users/client.py rename to src/webflow/resources/sites/resources/forms/client.py index d690c0f..7b253a9 100644 --- a/src/webflow/resources/users/client.py +++ b/src/webflow/resources/sites/resources/forms/client.py @@ -1,73 +1,74 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ...core.client_wrapper import SyncClientWrapper -from .types.users_list_request_sort import UsersListRequestSort -from ...core.request_options import RequestOptions -from ...types.user_list import UserList -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.forbidden_error import ForbiddenError -from ...errors.not_found_error import NotFoundError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError +from .....core.client_wrapper import SyncClientWrapper +from .....core.request_options import RequestOptions +from .....types.form_submission_list import FormSubmissionList +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as +from .....errors.bad_request_error import BadRequestError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....errors.forbidden_error import ForbiddenError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.internal_server_error import InternalServerError from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ...types.user import User -from .types.users_update_request_data import UsersUpdateRequestData -from ...core.serialization import convert_and_respect_annotation_metadata -from ...errors.conflict_error import ConflictError -from ...core.client_wrapper import AsyncClientWrapper +from .....core.api_error import ApiError +from .....types.form_submission import FormSubmission +from .....errors.conflict_error import ConflictError +from .....core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) -class UsersClient: +class FormsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper - def list( + def list_submissions_by_site( self, site_id: str, *, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, - sort: typing.Optional[UsersListRequestSort] = None, + element_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> UserList: + ) -> FormSubmissionList: """ - Get a list of users for a site + List all form submissions for a given site with the ability to filter submissions by a centralized `elementId`. - Required scope | `users:read` + Add `elementId` when you want to filter form submissions to a specific form in a site. You can get the `elementId` from the [List forms endpoint](/data/reference/forms/forms/list) (displayed as `formElementId` in the response). + + + When a form is used in a Webflow component definition, each instance of the component will yield a unique form. Adding the `elementId` in this request ensures this API response includes all submissions from that core form, wherever that form is used in instantiated components. + + + Use the [List Form Submissions endpoint](/data/reference/forms/form-submissions/list-submissions) to list form submissions for a given form ID. + + Required scope | `forms:read` Parameters ---------- site_id : str Unique identifier for a Site - offset : typing.Optional[float] + element_id : typing.Optional[str] + Identifier for an element + + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - sort : typing.Optional[UsersListRequestSort] - Sort string to use when ordering users - - Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). - - Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) - request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - UserList + FormSubmissionList Request was successful Examples @@ -77,26 +78,30 @@ def list( client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) - client.users.list( + client.sites.forms.list_submissions_by_site( site_id="580e63e98c9a982ac9b8b741", + element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0", + offset=1, + limit=1, ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/users", + f"sites/{jsonable_encoder(site_id)}/form_submissions", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ + "elementId": element_id, "offset": offset, "limit": limit, - "sort": sort, }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: return typing.cast( - UserList, + FormSubmissionList, parse_obj_as( - type_=UserList, # type: ignore + type_=FormSubmissionList, # type: ignore object_=_response.json(), ), ) @@ -165,26 +170,42 @@ def list( raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> User: + def list_submissions( + self, + site_id: str, + form_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> FormSubmissionList: """ - Get a User by ID + List form submissions for a given form ID within a specific site. + + Use the [List Form Submissions by Site endpoint](/data/reference/forms/form-submissions/list-submissions-by-site) to list form submissions for a given site with the ability to filter by a `formElementId`. - Required scope | `users:read` + Required scope | `forms:read` Parameters ---------- site_id : str Unique identifier for a Site - user_id : str - Unique identifier for a User + form_id : str + Unique identifier for a Form + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - User + FormSubmissionList Request was successful Examples @@ -194,22 +215,29 @@ def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[Re client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) - client.users.get( + client.sites.forms.list_submissions( site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", + form_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + f"sites/{jsonable_encoder(site_id)}/forms/{jsonable_encoder(form_id)}/submissions", + base_url=self._client_wrapper.get_environment().base, method="GET", + params={ + "offset": offset, + "limit": limit, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: return typing.cast( - User, + FormSubmissionList, parse_obj_as( - type_=User, # type: ignore + type_=FormSubmissionList, # type: ignore object_=_response.json(), ), ) @@ -278,26 +306,29 @@ def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[Re raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - def delete(self, site_id: str, user_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: + def get_submission( + self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> FormSubmission: """ - Delete a User by ID + Get information about a form submission within a specific site. - Required scope | `users:write` + Required scope | `forms:read` Parameters ---------- site_id : str Unique identifier for a Site - user_id : str - Unique identifier for a User + form_submission_id : str + Unique identifier for a Form Submission request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - None + FormSubmission + Request was successful Examples -------- @@ -306,19 +337,26 @@ def delete(self, site_id: str, user_id: str, *, request_options: typing.Optional client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) - client.users.delete( + client.sites.forms.get_submission( site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", + form_submission_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", - method="DELETE", + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return + return typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: raise BadRequestError( typing.cast( @@ -384,88 +422,50 @@ def delete(self, site_id: str, user_id: str, *, request_options: typing.Optional raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - def update( - self, - site_id: str, - user_id: str, - *, - data: typing.Optional[UsersUpdateRequestData] = OMIT, - access_groups: typing.Optional[typing.Sequence[str]] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> User: + def delete_submission( + self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: """ - Update a User by ID + Delete a form submission within a specific site. - Required scope | `users:write` - - The email and password - fields cannot be updated using this endpoint + Required scope | `forms:write` Parameters ---------- site_id : str Unique identifier for a Site - user_id : str - Unique identifier for a User - - data : typing.Optional[UsersUpdateRequestData] - - access_groups : typing.Optional[typing.Sequence[str]] - An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. - + form_submission_id : str + Unique identifier for a Form Submission request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - User - Request was successful + None Examples -------- from webflow import Webflow - from webflow.resources.users import UsersUpdateRequestData client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) - client.users.update( + client.sites.forms.delete_submission( site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", - data=UsersUpdateRequestData( - name="Some One", - accept_privacy=False, - accept_communications=False, - ), - access_groups=["webflowers", "platinum", "free-tier"], + form_submission_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", - method="PATCH", - json={ - "data": convert_and_respect_annotation_metadata( - object_=data, annotation=UsersUpdateRequestData, direction="write" - ), - "accessGroups": access_groups, - }, - headers={ - "content-type": "application/json", - }, + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", request_options=request_options, - omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return typing.cast( - User, - parse_obj_as( - type_=User, # type: ignore - object_=_response.json(), - ), - ) + return if _response.status_code == 400: raise BadRequestError( typing.cast( @@ -506,6 +506,16 @@ def update( ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -531,39 +541,36 @@ def update( raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - def invite( + def update_submission( self, site_id: str, + form_submission_id: str, *, - email: str, - access_groups: typing.Optional[typing.Sequence[str]] = OMIT, + form_submission_data: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> User: + ) -> FormSubmission: """ - Create and invite a user with an email address. + Update hidden fields on a form submission within a specific site. - The user will be sent and invite via email, which they will need to accept in order to join paid any paid access group. - - Required scope | `users:write` + Required scope | `forms:write` Parameters ---------- site_id : str Unique identifier for a Site - email : str - Email address of user to send invite to - - access_groups : typing.Optional[typing.Sequence[str]] - An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. + form_submission_id : str + Unique identifier for a Form Submission + form_submission_data : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + An existing **hidden field** defined on the form schema, and the corresponding value to set request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - User + FormSubmission Request was successful Examples @@ -573,18 +580,17 @@ def invite( client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) - client.users.invite( + client.sites.forms.update_submission( site_id="580e63e98c9a982ac9b8b741", - email="some.one@home.com", - access_groups=["webflowers"], + form_submission_id="580e63e98c9a982ac9b8b741", ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/users/invite", - method="POST", + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", json={ - "email": email, - "accessGroups": access_groups, + "formSubmissionData": form_submission_data, }, headers={ "content-type": "application/json", @@ -595,9 +601,9 @@ def invite( try: if 200 <= _response.status_code < 300: return typing.cast( - User, + FormSubmission, parse_obj_as( - type_=User, # type: ignore + type_=FormSubmission, # type: ignore object_=_response.json(), ), ) @@ -677,48 +683,52 @@ def invite( raise ApiError(status_code=_response.status_code, body=_response_json) -class AsyncUsersClient: +class AsyncFormsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper - async def list( + async def list_submissions_by_site( self, site_id: str, *, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, - sort: typing.Optional[UsersListRequestSort] = None, + element_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> UserList: + ) -> FormSubmissionList: """ - Get a list of users for a site + List all form submissions for a given site with the ability to filter submissions by a centralized `elementId`. + + Add `elementId` when you want to filter form submissions to a specific form in a site. You can get the `elementId` from the [List forms endpoint](/data/reference/forms/forms/list) (displayed as `formElementId` in the response). - Required scope | `users:read` + + When a form is used in a Webflow component definition, each instance of the component will yield a unique form. Adding the `elementId` in this request ensures this API response includes all submissions from that core form, wherever that form is used in instantiated components. + + + Use the [List Form Submissions endpoint](/data/reference/forms/form-submissions/list-submissions) to list form submissions for a given form ID. + + Required scope | `forms:read` Parameters ---------- site_id : str Unique identifier for a Site - offset : typing.Optional[float] + element_id : typing.Optional[str] + Identifier for an element + + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) - sort : typing.Optional[UsersListRequestSort] - Sort string to use when ordering users - - Example(`CreatedOn`, `Email`, `Status`, `LastLogin`, `UpdatedOn`). - - Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) - request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - UserList + FormSubmissionList Request was successful Examples @@ -733,29 +743,33 @@ async def list( async def main() -> None: - await client.users.list( + await client.sites.forms.list_submissions_by_site( site_id="580e63e98c9a982ac9b8b741", + element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0", + offset=1, + limit=1, ) asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/users", + f"sites/{jsonable_encoder(site_id)}/form_submissions", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ + "elementId": element_id, "offset": offset, "limit": limit, - "sort": sort, }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: return typing.cast( - UserList, + FormSubmissionList, parse_obj_as( - type_=UserList, # type: ignore + type_=FormSubmissionList, # type: ignore object_=_response.json(), ), ) @@ -824,26 +838,42 @@ async def main() -> None: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - async def get(self, site_id: str, user_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> User: + async def list_submissions( + self, + site_id: str, + form_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> FormSubmissionList: """ - Get a User by ID + List form submissions for a given form ID within a specific site. + + Use the [List Form Submissions by Site endpoint](/data/reference/forms/form-submissions/list-submissions-by-site) to list form submissions for a given site with the ability to filter by a `formElementId`. - Required scope | `users:read` + Required scope | `forms:read` Parameters ---------- site_id : str Unique identifier for a Site - user_id : str - Unique identifier for a User + form_id : str + Unique identifier for a Form + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - User + FormSubmissionList Request was successful Examples @@ -858,25 +888,32 @@ async def get(self, site_id: str, user_id: str, *, request_options: typing.Optio async def main() -> None: - await client.users.get( + await client.sites.forms.list_submissions( site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", + form_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", + f"sites/{jsonable_encoder(site_id)}/forms/{jsonable_encoder(form_id)}/submissions", + base_url=self._client_wrapper.get_environment().base, method="GET", + params={ + "offset": offset, + "limit": limit, + }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: return typing.cast( - User, + FormSubmissionList, parse_obj_as( - type_=User, # type: ignore + type_=FormSubmissionList, # type: ignore object_=_response.json(), ), ) @@ -945,28 +982,29 @@ async def main() -> None: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - async def delete( - self, site_id: str, user_id: str, *, request_options: typing.Optional[RequestOptions] = None - ) -> None: + async def get_submission( + self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> FormSubmission: """ - Delete a User by ID + Get information about a form submission within a specific site. - Required scope | `users:write` + Required scope | `forms:read` Parameters ---------- site_id : str Unique identifier for a Site - user_id : str - Unique identifier for a User + form_submission_id : str + Unique identifier for a Form Submission request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - None + FormSubmission + Request was successful Examples -------- @@ -980,22 +1018,29 @@ async def delete( async def main() -> None: - await client.users.delete( + await client.sites.forms.get_submission( site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", + form_submission_id="580e63e98c9a982ac9b8b741", ) asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", - method="DELETE", + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", request_options=request_options, ) try: if 200 <= _response.status_code < 300: - return + return typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) if _response.status_code == 400: raise BadRequestError( typing.cast( @@ -1061,51 +1106,34 @@ async def main() -> None: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - async def update( - self, - site_id: str, - user_id: str, - *, - data: typing.Optional[UsersUpdateRequestData] = OMIT, - access_groups: typing.Optional[typing.Sequence[str]] = OMIT, - request_options: typing.Optional[RequestOptions] = None, - ) -> User: + async def delete_submission( + self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: """ - Update a User by ID - - Required scope | `users:write` + Delete a form submission within a specific site. - The email and password - fields cannot be updated using this endpoint + Required scope | `forms:write` Parameters ---------- site_id : str Unique identifier for a Site - user_id : str - Unique identifier for a User - - data : typing.Optional[UsersUpdateRequestData] - - access_groups : typing.Optional[typing.Sequence[str]] - An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. - + form_submission_id : str + Unique identifier for a Form Submission request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - User - Request was successful + None Examples -------- import asyncio from webflow import AsyncWebflow - from webflow.resources.users import UsersUpdateRequestData client = AsyncWebflow( access_token="YOUR_ACCESS_TOKEN", @@ -1113,44 +1141,23 @@ async def update( async def main() -> None: - await client.users.update( + await client.sites.forms.delete_submission( site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", - data=UsersUpdateRequestData( - name="Some One", - accept_privacy=False, - accept_communications=False, - ), - access_groups=["webflowers", "platinum", "free-tier"], + form_submission_id="580e63e98c9a982ac9b8b741", ) asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/users/{jsonable_encoder(user_id)}", - method="PATCH", - json={ - "data": convert_and_respect_annotation_metadata( - object_=data, annotation=UsersUpdateRequestData, direction="write" - ), - "accessGroups": access_groups, - }, - headers={ - "content-type": "application/json", - }, + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", request_options=request_options, - omit=OMIT, ) try: if 200 <= _response.status_code < 300: - return typing.cast( - User, - parse_obj_as( - type_=User, # type: ignore - object_=_response.json(), - ), - ) + return if _response.status_code == 400: raise BadRequestError( typing.cast( @@ -1191,6 +1198,16 @@ async def main() -> None: ), ) ) + if _response.status_code == 409: + raise ConflictError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) if _response.status_code == 429: raise TooManyRequestsError( typing.cast( @@ -1216,39 +1233,36 @@ async def main() -> None: raise ApiError(status_code=_response.status_code, body=_response.text) raise ApiError(status_code=_response.status_code, body=_response_json) - async def invite( + async def update_submission( self, site_id: str, + form_submission_id: str, *, - email: str, - access_groups: typing.Optional[typing.Sequence[str]] = OMIT, + form_submission_data: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, request_options: typing.Optional[RequestOptions] = None, - ) -> User: + ) -> FormSubmission: """ - Create and invite a user with an email address. - - The user will be sent and invite via email, which they will need to accept in order to join paid any paid access group. + Update hidden fields on a form submission within a specific site. - Required scope | `users:write` + Required scope | `forms:write` Parameters ---------- site_id : str Unique identifier for a Site - email : str - Email address of user to send invite to - - access_groups : typing.Optional[typing.Sequence[str]] - An array of access group slugs. Access groups are assigned to the user as type `admin` and the user remains in the group until removed. + form_submission_id : str + Unique identifier for a Form Submission + form_submission_data : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + An existing **hidden field** defined on the form schema, and the corresponding value to set request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - User + FormSubmission Request was successful Examples @@ -1263,21 +1277,20 @@ async def invite( async def main() -> None: - await client.users.invite( + await client.sites.forms.update_submission( site_id="580e63e98c9a982ac9b8b741", - email="some.one@home.com", - access_groups=["webflowers"], + form_submission_id="580e63e98c9a982ac9b8b741", ) asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/users/invite", - method="POST", + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", json={ - "email": email, - "accessGroups": access_groups, + "formSubmissionData": form_submission_data, }, headers={ "content-type": "application/json", @@ -1288,9 +1301,9 @@ async def main() -> None: try: if 200 <= _response.status_code < 300: return typing.cast( - User, + FormSubmission, parse_obj_as( - type_=User, # type: ignore + type_=FormSubmission, # type: ignore object_=_response.json(), ), ) diff --git a/src/webflow/resources/sites/resources/plans/client.py b/src/webflow/resources/sites/resources/plans/client.py index 291231a..a3309bb 100644 --- a/src/webflow/resources/sites/resources/plans/client.py +++ b/src/webflow/resources/sites/resources/plans/client.py @@ -25,6 +25,8 @@ def get_site_plan(self, site_id: str, *, request_options: typing.Optional[Reques """ Get site plan details for the specified Site. + This endpoint requires an Enterprise workspace. + Required scope | `sites:read` Parameters @@ -53,6 +55,7 @@ def get_site_plan(self, site_id: str, *, request_options: typing.Optional[Reques """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/plan", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -129,6 +132,8 @@ async def get_site_plan(self, site_id: str, *, request_options: typing.Optional[ """ Get site plan details for the specified Site. + This endpoint requires an Enterprise workspace. + Required scope | `sites:read` Parameters @@ -165,6 +170,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/plan", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) diff --git a/src/webflow/resources/sites/resources/redirects/client.py b/src/webflow/resources/sites/resources/redirects/client.py index 4bc0e7b..1ac17b4 100644 --- a/src/webflow/resources/sites/resources/redirects/client.py +++ b/src/webflow/resources/sites/resources/redirects/client.py @@ -27,10 +27,11 @@ def __init__(self, *, client_wrapper: SyncClientWrapper): def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Redirects: """ - Fetch a list of all URL redirect rules configured for a specific site. + Fetch a list of all 301 redirect rules configured for a specific site. Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + This endpoint requires an Enterprise workspace. Required scope: `sites:read` @@ -60,6 +61,7 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -137,10 +139,12 @@ def create( request_options: typing.Optional[RequestOptions] = None, ) -> Redirect: """ - Add a new URL redirection rule to a site. + Add a new 301 redirection rule to a site. This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -181,6 +185,7 @@ def create( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "id": id, @@ -258,8 +263,12 @@ def delete( self, site_id: str, redirect_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> Redirects: """ - Remove a URL redirection rule from a site. + Remove a 301 redirection rule from a site. + This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -292,6 +301,7 @@ def delete( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -370,7 +380,10 @@ def update( request_options: typing.Optional[RequestOptions] = None, ) -> Redirect: """ - Update a URL redirection rule from a site. + Update a 301 redirection rule from a site. + + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -415,6 +428,7 @@ def update( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "id": id, @@ -495,10 +509,11 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper): async def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Redirects: """ - Fetch a list of all URL redirect rules configured for a specific site. + Fetch a list of all 301 redirect rules configured for a specific site. Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + This endpoint requires an Enterprise workspace. Required scope: `sites:read` @@ -536,6 +551,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -613,10 +629,12 @@ async def create( request_options: typing.Optional[RequestOptions] = None, ) -> Redirect: """ - Add a new URL redirection rule to a site. + Add a new 301 redirection rule to a site. This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -665,6 +683,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "id": id, @@ -742,8 +761,12 @@ async def delete( self, site_id: str, redirect_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> Redirects: """ - Remove a URL redirection rule from a site. + Remove a 301 redirection rule from a site. + This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -784,6 +807,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -862,7 +886,10 @@ async def update( request_options: typing.Optional[RequestOptions] = None, ) -> Redirect: """ - Update a URL redirection rule from a site. + Update a 301 redirection rule from a site. + + This endpoint requires an Enterprise workspace. + Required scope: `sites:write` Parameters @@ -915,6 +942,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, method="PATCH", json={ "id": id, diff --git a/src/webflow/types/duplicate_user_email.py b/src/webflow/resources/sites/resources/robots_txt/__init__.py similarity index 50% rename from src/webflow/types/duplicate_user_email.py rename to src/webflow/resources/sites/resources/robots_txt/__init__.py index 4a44039..f3ea265 100644 --- a/src/webflow/types/duplicate_user_email.py +++ b/src/webflow/resources/sites/resources/robots_txt/__init__.py @@ -1,5 +1,2 @@ # This file was auto-generated by Fern from our API Definition. -import typing - -DuplicateUserEmail = typing.Optional[typing.Any] diff --git a/src/webflow/resources/sites/resources/robots_txt/client.py b/src/webflow/resources/sites/resources/robots_txt/client.py new file mode 100644 index 0000000..a0bc59b --- /dev/null +++ b/src/webflow/resources/sites/resources/robots_txt/client.py @@ -0,0 +1,1050 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .....core.client_wrapper import SyncClientWrapper +from .....core.request_options import RequestOptions +from .....types.robots import Robots +from .....core.jsonable_encoder import jsonable_encoder +from .....core.pydantic_utilities import parse_obj_as +from .....errors.bad_request_error import BadRequestError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .....types.robots_rules_item import RobotsRulesItem +from .....core.serialization import convert_and_respect_annotation_metadata +from .....core.client_wrapper import AsyncClientWrapper + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RobotsTxtClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Robots: + """ + Retrieve the robots.txt configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.robots_txt.get( + site_id="580e63e98c9a982ac9b8b741", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def put( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Replace the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + from webflow import RobotsRulesItem, Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.robots_txt.put( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Remove specific rules for a user-agent in your `robots.txt` file. To delete all rules for a user-agent, provide an empty rule set. This will remove the user-agent's entry entirely, leaving it subject to your site's default crawling behavior. + + **Note:** Deleting a user-agent with no rules will make the user-agent's access unrestricted unless other directives apply. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + from webflow import RobotsRulesItem, Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.robots_txt.delete( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="*", + allows=["/public"], + disallows=["/bubbles"], + ) + ], + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def patch( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Update the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + from webflow import RobotsRulesItem, Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.robots_txt.patch( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncRobotsTxtClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Robots: + """ + Retrieve the robots.txt configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.robots_txt.get( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def put( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Replace the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow, RobotsRulesItem + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.robots_txt.put( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Remove specific rules for a user-agent in your `robots.txt` file. To delete all rules for a user-agent, provide an empty rule set. This will remove the user-agent's entry entirely, leaving it subject to your site's default crawling behavior. + + **Note:** Deleting a user-agent with no rules will make the user-agent's access unrestricted unless other directives apply. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow, RobotsRulesItem + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.robots_txt.delete( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="*", + allows=["/public"], + disallows=["/bubbles"], + ) + ], + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def patch( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Robots: + """ + Update the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Robots + Request was successful + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow, RobotsRulesItem + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.robots_txt.patch( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", + allows=["/public"], + disallows=["/vogon-poetry", "/total-perspective-vortex"], + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/webflow/resources/sites/resources/scripts/client.py b/src/webflow/resources/sites/resources/scripts/client.py index 1954842..7966e56 100644 --- a/src/webflow/resources/sites/resources/scripts/client.py +++ b/src/webflow/resources/sites/resources/scripts/client.py @@ -31,9 +31,11 @@ def get_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Site. + Get all scripts applied to a site by the App. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -63,6 +65,7 @@ def get_custom_code( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -140,13 +143,11 @@ def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Site. + Apply registered scripts to a site. If you have multiple scripts your App needs to apply or maintain on a site, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -198,6 +199,7 @@ def upsert_custom_code( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="PUT", json={ "scripts": convert_and_respect_annotation_metadata( @@ -275,9 +277,11 @@ def upsert_custom_code( def delete_custom_code(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ - Delete the custom code block that an app created for a Site + Remove all scripts from a site applied by the App. This endpoint will not remove scripts from the site's registered scripts. + + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-sites/upsert-custom-code) endpoint. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write` @@ -306,6 +310,7 @@ def delete_custom_code(self, site_id: str, *, request_options: typing.Optional[R """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -371,14 +376,18 @@ def list_custom_code_blocks( self, site_id: str, *, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ListCustomCodeBlocks: """ - Get all instances of Custom Code applied to a Site or Pages. + Get a list of scripts that have been applied to a site and/or individual pages. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -387,10 +396,10 @@ def list_custom_code_blocks( site_id : str Unique identifier for a Site - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) request_options : typing.Optional[RequestOptions] @@ -410,10 +419,13 @@ def list_custom_code_blocks( ) client.sites.scripts.list_custom_code_blocks( site_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, @@ -494,9 +506,11 @@ async def get_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> ScriptApplyList: """ - Get all registered scripts that have been applied to a specific Site. + Get all scripts applied to a site by the App. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -534,6 +548,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -611,13 +626,11 @@ async def upsert_custom_code( request_options: typing.Optional[RequestOptions] = None, ) -> ScriptApplyList: """ - Add a registered script to a Site. + Apply registered scripts to a site. If you have multiple scripts your App needs to apply or maintain on a site, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. - In order to use the Custom Code APIs for Sites and Pages, Custom Code Scripts must first be registered - to a Site via the `registered_scripts` endpoints, and then applied to a Site or Page using the appropriate - `custom_code` endpoints. - - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:write` @@ -677,6 +690,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="PUT", json={ "scripts": convert_and_respect_annotation_metadata( @@ -756,9 +770,11 @@ async def delete_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None ) -> None: """ - Delete the custom code block that an app created for a Site + Remove all scripts from a site applied by the App. This endpoint will not remove scripts from the site's registered scripts. + + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-sites/upsert-custom-code) endpoint. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). Required scope | `custom_code:write` @@ -795,6 +811,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -860,14 +877,18 @@ async def list_custom_code_blocks( self, site_id: str, *, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None, ) -> ListCustomCodeBlocks: """ - Get all instances of Custom Code applied to a Site or Pages. + Get a list of scripts that have been applied to a site and/or individual pages. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. - Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + Required scope | `custom_code:read` @@ -876,10 +897,10 @@ async def list_custom_code_blocks( site_id : str Unique identifier for a Site - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] + limit : typing.Optional[int] Maximum number of records to be returned (max limit: 100) request_options : typing.Optional[RequestOptions] @@ -904,6 +925,8 @@ async def list_custom_code_blocks( async def main() -> None: await client.sites.scripts.list_custom_code_blocks( site_id="580e63e98c9a982ac9b8b741", + offset=1, + limit=1, ) @@ -911,6 +934,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ "offset": offset, diff --git a/src/webflow/resources/sites/resources/well_known/__init__.py b/src/webflow/resources/sites/resources/well_known/__init__.py new file mode 100644 index 0000000..323b6bd --- /dev/null +++ b/src/webflow/resources/sites/resources/well_known/__init__.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import WellKnownFileContentType + +__all__ = ["WellKnownFileContentType"] diff --git a/src/webflow/resources/sites/resources/well_known/client.py b/src/webflow/resources/sites/resources/well_known/client.py new file mode 100644 index 0000000..3bba9ab --- /dev/null +++ b/src/webflow/resources/sites/resources/well_known/client.py @@ -0,0 +1,534 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .....core.client_wrapper import SyncClientWrapper +from .types.well_known_file_content_type import WellKnownFileContentType +from .....core.request_options import RequestOptions +from .....core.jsonable_encoder import jsonable_encoder +from .....errors.bad_request_error import BadRequestError +from .....core.pydantic_utilities import parse_obj_as +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.internal_server_error import InternalServerError +from json.decoder import JSONDecodeError +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class WellKnownClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def put( + self, + site_id: str, + *, + file_name: str, + file_data: str, + content_type: typing.Optional[WellKnownFileContentType] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Upload a supported well-known file to a site. + + The current restrictions on well-known files are as follows: + - Each file must be smaller than 100kb + - Less than 30 total files + - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` + + + `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. + + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_name : str + The name of the file + + file_data : str + The contents of the file + + content_type : typing.Optional[WellKnownFileContentType] + The content type of the file. Defaults to application/json + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.well_known.put( + site_id="580e63e98c9a982ac9b8b741", + file_name="apple-app-site-association.txt", + file_data='{\n "applinks": {\n "apps": [],\n "details": [\n {\n "appID": "ABCDE12345.com.example.app",\n "paths": [ "/*", "/some/path/*" ]\n }\n ]\n }\n}\n', + content_type="application/json", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "fileName": file_name, + "fileData": file_data, + "contentType": content_type, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def delete( + self, + site_id: str, + *, + file_names: typing.Optional[typing.Sequence[str]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Delete existing well-known files from a site. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_names : typing.Optional[typing.Sequence[str]] + A list of file names to delete + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from webflow import Webflow + + client = Webflow( + access_token="YOUR_ACCESS_TOKEN", + ) + client.sites.well_known.delete( + site_id="580e63e98c9a982ac9b8b741", + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "fileNames": file_names, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncWellKnownClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def put( + self, + site_id: str, + *, + file_name: str, + file_data: str, + content_type: typing.Optional[WellKnownFileContentType] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Upload a supported well-known file to a site. + + The current restrictions on well-known files are as follows: + - Each file must be smaller than 100kb + - Less than 30 total files + - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` + + + `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. + + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_name : str + The name of the file + + file_data : str + The contents of the file + + content_type : typing.Optional[WellKnownFileContentType] + The content type of the file. Defaults to application/json + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.well_known.put( + site_id="580e63e98c9a982ac9b8b741", + file_name="apple-app-site-association.txt", + file_data='{\n "applinks": {\n "apps": [],\n "details": [\n {\n "appID": "ABCDE12345.com.example.app",\n "paths": [ "/*", "/some/path/*" ]\n }\n ]\n }\n}\n', + content_type="application/json", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "fileName": file_name, + "fileData": file_data, + "contentType": content_type, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def delete( + self, + site_id: str, + *, + file_names: typing.Optional[typing.Sequence[str]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Delete existing well-known files from a site. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_names : typing.Optional[typing.Sequence[str]] + A list of file names to delete + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from webflow import AsyncWebflow + + client = AsyncWebflow( + access_token="YOUR_ACCESS_TOKEN", + ) + + + async def main() -> None: + await client.sites.well_known.delete( + site_id="580e63e98c9a982ac9b8b741", + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "fileNames": file_names, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return + if _response.status_code == 400: + raise BadRequestError( + typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 401: + raise UnauthorizedError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 404: + raise NotFoundError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 429: + raise TooManyRequestsError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + if _response.status_code == 500: + raise InternalServerError( + typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/webflow/resources/sites/resources/well_known/types/__init__.py b/src/webflow/resources/sites/resources/well_known/types/__init__.py new file mode 100644 index 0000000..4fc9c09 --- /dev/null +++ b/src/webflow/resources/sites/resources/well_known/types/__init__.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .well_known_file_content_type import WellKnownFileContentType + +__all__ = ["WellKnownFileContentType"] diff --git a/src/webflow/resources/sites/resources/well_known/types/well_known_file_content_type.py b/src/webflow/resources/sites/resources/well_known/types/well_known_file_content_type.py new file mode 100644 index 0000000..be135b4 --- /dev/null +++ b/src/webflow/resources/sites/resources/well_known/types/well_known_file_content_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WellKnownFileContentType = typing.Union[typing.Literal["application/json", "text/plain"], typing.Any] diff --git a/src/webflow/resources/token/client.py b/src/webflow/resources/token/client.py index 628ce3a..d8cfd16 100644 --- a/src/webflow/resources/token/client.py +++ b/src/webflow/resources/token/client.py @@ -45,6 +45,7 @@ def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = No """ _response = self._client_wrapper.httpx_client.request( "token/authorized_by", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -109,6 +110,7 @@ def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) """ _response = self._client_wrapper.httpx_client.request( "token/introspect", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -176,6 +178,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( "token/authorized_by", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -248,6 +251,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( "token/introspect", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) diff --git a/src/webflow/resources/users/__init__.py b/src/webflow/resources/users/__init__.py deleted file mode 100644 index 88e72a2..0000000 --- a/src/webflow/resources/users/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .types import UsersListRequestSort, UsersUpdateRequestData - -__all__ = ["UsersListRequestSort", "UsersUpdateRequestData"] diff --git a/src/webflow/resources/users/types/__init__.py b/src/webflow/resources/users/types/__init__.py deleted file mode 100644 index cadf367..0000000 --- a/src/webflow/resources/users/types/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .users_list_request_sort import UsersListRequestSort -from .users_update_request_data import UsersUpdateRequestData - -__all__ = ["UsersListRequestSort", "UsersUpdateRequestData"] diff --git a/src/webflow/resources/users/types/users_list_request_sort.py b/src/webflow/resources/users/types/users_list_request_sort.py deleted file mode 100644 index e4143a4..0000000 --- a/src/webflow/resources/users/types/users_list_request_sort.py +++ /dev/null @@ -1,19 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -UsersListRequestSort = typing.Union[ - typing.Literal[ - "CreatedOn", - "-CreatedOn", - "Email", - "-Email", - "Status", - "-Status", - "LastLogin", - "-LastLogin", - "UpdatedOn", - "-UpdatedOn", - ], - typing.Any, -] diff --git a/src/webflow/resources/users/types/users_update_request_data.py b/src/webflow/resources/users/types/users_update_request_data.py deleted file mode 100644 index 919406c..0000000 --- a/src/webflow/resources/users/types/users_update_request_data.py +++ /dev/null @@ -1,38 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ....core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic -import typing_extensions -from ....core.serialization import FieldMetadata -from ....core.pydantic_utilities import IS_PYDANTIC_V2 - - -class UsersUpdateRequestData(UniversalBaseModel): - name: typing.Optional[str] = pydantic.Field(default=None) - """ - The name of the user - """ - - accept_privacy: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="accept-privacy")] = ( - pydantic.Field(default=None) - ) - """ - Boolean indicating if the user has accepted the privacy policy - """ - - accept_communications: typing_extensions.Annotated[ - typing.Optional[bool], FieldMetadata(alias="accept-communications") - ] = pydantic.Field(default=None) - """ - Boolean indicating if the user has accepted to receive communications - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/webflow/resources/webhooks/client.py b/src/webflow/resources/webhooks/client.py index ded9a2f..c6821a9 100644 --- a/src/webflow/resources/webhooks/client.py +++ b/src/webflow/resources/webhooks/client.py @@ -61,6 +61,7 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/webhooks", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -212,6 +213,7 @@ def create( """ _response = self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id_)}/webhooks", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "id": id, @@ -324,6 +326,7 @@ def get(self, webhook_id: str, *, request_options: typing.Optional[RequestOption """ _response = self._client_wrapper.httpx_client.request( f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -422,6 +425,7 @@ def delete(self, webhook_id: str, *, request_options: typing.Optional[RequestOpt """ _response = self._client_wrapper.httpx_client.request( f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) @@ -528,6 +532,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id)}/webhooks", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -686,6 +691,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"sites/{jsonable_encoder(site_id_)}/webhooks", + base_url=self._client_wrapper.get_environment().base, method="POST", json={ "id": id, @@ -806,6 +812,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, method="GET", request_options=request_options, ) @@ -912,6 +919,7 @@ async def main() -> None: """ _response = await self._client_wrapper.httpx_client.request( f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, method="DELETE", request_options=request_options, ) diff --git a/src/webflow/resources/workspaces/__init__.py b/src/webflow/resources/workspaces/__init__.py new file mode 100644 index 0000000..d6cc054 --- /dev/null +++ b/src/webflow/resources/workspaces/__init__.py @@ -0,0 +1,13 @@ +# This file was auto-generated by Fern from our API Definition. + +from .resources import ( + AuditLogsGetWorkspaceAuditLogsRequestEventType, + AuditLogsGetWorkspaceAuditLogsRequestSortOrder, + audit_logs, +) + +__all__ = [ + "AuditLogsGetWorkspaceAuditLogsRequestEventType", + "AuditLogsGetWorkspaceAuditLogsRequestSortOrder", + "audit_logs", +] diff --git a/src/webflow/resources/workspaces/client.py b/src/webflow/resources/workspaces/client.py new file mode 100644 index 0000000..de70ca5 --- /dev/null +++ b/src/webflow/resources/workspaces/client.py @@ -0,0 +1,18 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.client_wrapper import SyncClientWrapper +from .resources.audit_logs.client import AuditLogsClient +from ...core.client_wrapper import AsyncClientWrapper +from .resources.audit_logs.client import AsyncAuditLogsClient + + +class WorkspacesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + self.audit_logs = AuditLogsClient(client_wrapper=self._client_wrapper) + + +class AsyncWorkspacesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + self.audit_logs = AsyncAuditLogsClient(client_wrapper=self._client_wrapper) diff --git a/src/webflow/resources/workspaces/resources/__init__.py b/src/webflow/resources/workspaces/resources/__init__.py new file mode 100644 index 0000000..0e96a0e --- /dev/null +++ b/src/webflow/resources/workspaces/resources/__init__.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +from . import audit_logs +from .audit_logs import AuditLogsGetWorkspaceAuditLogsRequestEventType, AuditLogsGetWorkspaceAuditLogsRequestSortOrder + +__all__ = [ + "AuditLogsGetWorkspaceAuditLogsRequestEventType", + "AuditLogsGetWorkspaceAuditLogsRequestSortOrder", + "audit_logs", +] diff --git a/src/webflow/resources/workspaces/resources/audit_logs/__init__.py b/src/webflow/resources/workspaces/resources/audit_logs/__init__.py new file mode 100644 index 0000000..dab3df1 --- /dev/null +++ b/src/webflow/resources/workspaces/resources/audit_logs/__init__.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .types import AuditLogsGetWorkspaceAuditLogsRequestEventType, AuditLogsGetWorkspaceAuditLogsRequestSortOrder + +__all__ = ["AuditLogsGetWorkspaceAuditLogsRequestEventType", "AuditLogsGetWorkspaceAuditLogsRequestSortOrder"] diff --git a/src/webflow/resources/access_groups/client.py b/src/webflow/resources/workspaces/resources/audit_logs/client.py similarity index 52% rename from src/webflow/resources/access_groups/client.py rename to src/webflow/resources/workspaces/resources/audit_logs/client.py index ee7668a..dcbded2 100644 --- a/src/webflow/resources/access_groups/client.py +++ b/src/webflow/resources/workspaces/resources/audit_logs/client.py @@ -1,105 +1,126 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.client_wrapper import SyncClientWrapper +from .....core.client_wrapper import SyncClientWrapper import typing -from .types.access_groups_list_request_sort import AccessGroupsListRequestSort -from ...core.request_options import RequestOptions -from ...types.access_group_list import AccessGroupList -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.forbidden_error import ForbiddenError -from ...errors.not_found_error import NotFoundError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError +from .types.audit_logs_get_workspace_audit_logs_request_sort_order import AuditLogsGetWorkspaceAuditLogsRequestSortOrder +from .types.audit_logs_get_workspace_audit_logs_request_event_type import AuditLogsGetWorkspaceAuditLogsRequestEventType +import datetime as dt +from .....core.request_options import RequestOptions +from .....types.workspace_audit_log_response import WorkspaceAuditLogResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.datetime_utils import serialize_datetime +from .....core.pydantic_utilities import parse_obj_as +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....errors.forbidden_error import ForbiddenError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.internal_server_error import InternalServerError from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper -class AccessGroupsClient: +class AuditLogsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper - def list( + def get_workspace_audit_logs( self, - site_id: str, + workspace_id_or_slug: str, *, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, - sort: typing.Optional[AccessGroupsListRequestSort] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + sort_order: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] = None, + event_type: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] = None, + from_: typing.Optional[dt.datetime] = None, + to: typing.Optional[dt.datetime] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AccessGroupList: + ) -> WorkspaceAuditLogResponse: """ - Get a list of access groups for a site + Get audit logs for a workspace. - Required scope | `users:read` + This endpoint requires an Enterprise workspace and a workspace token with the `workspace_activity:read` scope. Create a workspace token from your workspace dashboard integrations page to use this endpoint. + + Required scope | `workspace_activity:read` Parameters ---------- - site_id : str - Unique identifier for a Site + workspace_id_or_slug : str + Unique identifier or slug for a Workspace + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] - Maximum number of records to be returned (max limit: 100) + sort_order : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] + Sorts the results by asc or desc + + event_type : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] + The event type to filter by - sort : typing.Optional[AccessGroupsListRequestSort] - Sort string to use when ordering access groups - Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) + from_ : typing.Optional[dt.datetime] + The start date to filter by + + to : typing.Optional[dt.datetime] + The end date to filter by request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - AccessGroupList - Request was successful + WorkspaceAuditLogResponse + A list of workspace audit logs Examples -------- + import datetime + from webflow import Webflow client = Webflow( access_token="YOUR_ACCESS_TOKEN", ) - client.access_groups.list( - site_id="580e63e98c9a982ac9b8b741", + client.workspaces.audit_logs.get_workspace_audit_logs( + workspace_id_or_slug="hitchhikers-workspace", + limit=1, + offset=1, + sort_order="asc", + event_type="user_access", + from_=datetime.datetime.fromisoformat( + "2025-06-22 16:00:31+00:00", + ), + to=datetime.datetime.fromisoformat( + "2025-07-22 16:00:31+00:00", + ), ) """ _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/accessgroups", + f"workspaces/{jsonable_encoder(workspace_id_or_slug)}/audit_logs", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ - "offset": offset, "limit": limit, - "sort": sort, + "offset": offset, + "sortOrder": sort_order, + "eventType": event_type, + "from": serialize_datetime(from_) if from_ is not None else None, + "to": serialize_datetime(to) if to is not None else None, }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: return typing.cast( - AccessGroupList, + WorkspaceAuditLogResponse, parse_obj_as( - type_=AccessGroupList, # type: ignore + type_=WorkspaceAuditLogResponse, # type: ignore object_=_response.json(), ), ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) if _response.status_code == 401: raise UnauthorizedError( typing.cast( @@ -156,50 +177,64 @@ def list( raise ApiError(status_code=_response.status_code, body=_response_json) -class AsyncAccessGroupsClient: +class AsyncAuditLogsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper - async def list( + async def get_workspace_audit_logs( self, - site_id: str, + workspace_id_or_slug: str, *, - offset: typing.Optional[float] = None, - limit: typing.Optional[float] = None, - sort: typing.Optional[AccessGroupsListRequestSort] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + sort_order: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] = None, + event_type: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] = None, + from_: typing.Optional[dt.datetime] = None, + to: typing.Optional[dt.datetime] = None, request_options: typing.Optional[RequestOptions] = None, - ) -> AccessGroupList: + ) -> WorkspaceAuditLogResponse: """ - Get a list of access groups for a site + Get audit logs for a workspace. - Required scope | `users:read` + This endpoint requires an Enterprise workspace and a workspace token with the `workspace_activity:read` scope. Create a workspace token from your workspace dashboard integrations page to use this endpoint. + + Required scope | `workspace_activity:read` Parameters ---------- - site_id : str - Unique identifier for a Site + workspace_id_or_slug : str + Unique identifier or slug for a Workspace + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) - offset : typing.Optional[float] + offset : typing.Optional[int] Offset used for pagination if the results have more than limit records - limit : typing.Optional[float] - Maximum number of records to be returned (max limit: 100) + sort_order : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] + Sorts the results by asc or desc - sort : typing.Optional[AccessGroupsListRequestSort] - Sort string to use when ordering access groups - Can be prefixed with a `-` to reverse the sort (ex. `-CreatedOn`) + event_type : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] + The event type to filter by + + from_ : typing.Optional[dt.datetime] + The start date to filter by + + to : typing.Optional[dt.datetime] + The end date to filter by request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- - AccessGroupList - Request was successful + WorkspaceAuditLogResponse + A list of workspace audit logs Examples -------- import asyncio + import datetime from webflow import AsyncWebflow @@ -209,42 +244,46 @@ async def list( async def main() -> None: - await client.access_groups.list( - site_id="580e63e98c9a982ac9b8b741", + await client.workspaces.audit_logs.get_workspace_audit_logs( + workspace_id_or_slug="hitchhikers-workspace", + limit=1, + offset=1, + sort_order="asc", + event_type="user_access", + from_=datetime.datetime.fromisoformat( + "2025-06-22 16:00:31+00:00", + ), + to=datetime.datetime.fromisoformat( + "2025-07-22 16:00:31+00:00", + ), ) asyncio.run(main()) """ _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/accessgroups", + f"workspaces/{jsonable_encoder(workspace_id_or_slug)}/audit_logs", + base_url=self._client_wrapper.get_environment().base, method="GET", params={ - "offset": offset, "limit": limit, - "sort": sort, + "offset": offset, + "sortOrder": sort_order, + "eventType": event_type, + "from": serialize_datetime(from_) if from_ is not None else None, + "to": serialize_datetime(to) if to is not None else None, }, request_options=request_options, ) try: if 200 <= _response.status_code < 300: return typing.cast( - AccessGroupList, + WorkspaceAuditLogResponse, parse_obj_as( - type_=AccessGroupList, # type: ignore + type_=WorkspaceAuditLogResponse, # type: ignore object_=_response.json(), ), ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) if _response.status_code == 401: raise UnauthorizedError( typing.cast( diff --git a/src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py b/src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py new file mode 100644 index 0000000..3decf29 --- /dev/null +++ b/src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py @@ -0,0 +1,6 @@ +# This file was auto-generated by Fern from our API Definition. + +from .audit_logs_get_workspace_audit_logs_request_event_type import AuditLogsGetWorkspaceAuditLogsRequestEventType +from .audit_logs_get_workspace_audit_logs_request_sort_order import AuditLogsGetWorkspaceAuditLogsRequestSortOrder + +__all__ = ["AuditLogsGetWorkspaceAuditLogsRequestEventType", "AuditLogsGetWorkspaceAuditLogsRequestSortOrder"] diff --git a/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_event_type.py b/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_event_type.py new file mode 100644 index 0000000..08c3185 --- /dev/null +++ b/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_event_type.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +AuditLogsGetWorkspaceAuditLogsRequestEventType = typing.Union[ + typing.Literal[ + "user_access", + "custom_role", + "workspace_membership", + "site_membership", + "workspace_invitation", + "workspace_setting", + ], + typing.Any, +] diff --git a/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_sort_order.py b/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_sort_order.py new file mode 100644 index 0000000..dd90d5f --- /dev/null +++ b/src/webflow/resources/workspaces/resources/audit_logs/types/audit_logs_get_workspace_audit_logs_request_sort_order.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +AuditLogsGetWorkspaceAuditLogsRequestSortOrder = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/webflow/types/__init__.py b/src/webflow/types/__init__.py index 5b2d8c6..94afb21 100644 --- a/src/webflow/types/__init__.py +++ b/src/webflow/types/__init__.py @@ -1,7 +1,5 @@ # This file was auto-generated by Fern from our API Definition. -from .access_group import AccessGroup -from .access_group_list import AccessGroupList from .application import Application from .asset import Asset from .asset_folder import AssetFolder @@ -19,6 +17,8 @@ from .bulk_collection_item_field_data import BulkCollectionItemFieldData from .collection import Collection from .collection_item import CollectionItem +from .collection_item_changed import CollectionItemChanged +from .collection_item_created import CollectionItemCreated from .collection_item_field_data import CollectionItemFieldData from .collection_item_list import CollectionItemList from .collection_item_list_no_pagination import CollectionItemListNoPagination @@ -27,10 +27,31 @@ from .collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData from .collection_item_post_single import CollectionItemPostSingle from .collection_item_post_single_field_data import CollectionItemPostSingleFieldData +from .collection_item_published import CollectionItemPublished +from .collection_item_removed import CollectionItemRemoved +from .collection_item_removed_payload import CollectionItemRemovedPayload +from .collection_item_removed_payload_field_data import CollectionItemRemovedPayloadFieldData +from .collection_item_unpublished import CollectionItemUnpublished +from .collection_item_unpublished_payload import CollectionItemUnpublishedPayload +from .collection_item_unpublished_payload_field_data import CollectionItemUnpublishedPayloadFieldData from .collection_item_with_id_input import CollectionItemWithIdInput from .collection_item_with_id_input_field_data import CollectionItemWithIdInputFieldData from .collection_list import CollectionList from .collection_list_array_item import CollectionListArrayItem +from .comment import Comment +from .comment_payload import CommentPayload +from .comment_payload_author import CommentPayloadAuthor +from .comment_payload_mentioned_users_item import CommentPayloadMentionedUsersItem +from .comment_reply import CommentReply +from .comment_reply_author import CommentReplyAuthor +from .comment_reply_list import CommentReplyList +from .comment_reply_list_pagination import CommentReplyListPagination +from .comment_reply_mentioned_users_item import CommentReplyMentionedUsersItem +from .comment_thread import CommentThread +from .comment_thread_author import CommentThreadAuthor +from .comment_thread_list import CommentThreadList +from .comment_thread_list_pagination import CommentThreadListPagination +from .comment_thread_mentioned_users_item import CommentThreadMentionedUsersItem from .component import Component from .component_dom import ComponentDom from .component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite @@ -42,20 +63,28 @@ from .component_properties import ComponentProperties from .component_property import ComponentProperty from .component_property_type import ComponentPropertyType -from .conflict_error_body import ConflictErrorBody +from .conflict import Conflict from .custom_code_block import CustomCodeBlock from .custom_code_block_type import CustomCodeBlockType from .custom_code_hosted_response import CustomCodeHostedResponse from .custom_code_inline_response import CustomCodeInlineResponse +from .custom_role import CustomRole +from .custom_role_audit_log_item import CustomRoleAuditLogItem +from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType from .dom import Dom from .domain import Domain from .domains import Domains -from .duplicate_user_email import DuplicateUserEmail from .ecommerce_settings import EcommerceSettings from .error import Error from .error_code import ErrorCode from .field import Field +from .field_create import FieldCreate from .field_type import FieldType +from .field_validations import FieldValidations +from .field_validations_additional_properties import FieldValidationsAdditionalProperties +from .field_validations_additional_properties_additional_properties import ( + FieldValidationsAdditionalPropertiesAdditionalProperties, +) from .forbidden_error_body import ForbiddenErrorBody from .form import Form from .form_field import FormField @@ -65,23 +94,45 @@ from .form_response_settings import FormResponseSettings from .form_submission import FormSubmission from .form_submission_list import FormSubmissionList +from .form_submission_trigger import FormSubmissionTrigger +from .form_submission_trigger_payload import FormSubmissionTriggerPayload +from .form_submission_trigger_payload_schema_item import FormSubmissionTriggerPayloadSchemaItem +from .form_submission_trigger_payload_schema_item_field_type import FormSubmissionTriggerPayloadSchemaItemFieldType from .image_node import ImageNode from .image_node_image import ImageNodeImage from .invalid_domain import InvalidDomain from .invalid_scopes import InvalidScopes from .inventory_item import InventoryItem from .inventory_item_inventory_type import InventoryItemInventoryType +from .items_list_items_live_request_last_published import ItemsListItemsLiveRequestLastPublished +from .items_list_items_request_last_published import ItemsListItemsRequestLastPublished from .list_custom_code_blocks import ListCustomCodeBlocks from .locale import Locale from .locales import Locales +from .metadata import Metadata +from .metadata_options_item import MetadataOptionsItem +from .new_order import NewOrder from .no_domains import NoDomains -from .node import Node, Node_ComponentInstance, Node_Image, Node_Text +from .node import ( + Node, + Node_ComponentInstance, + Node_Image, + Node_SearchButton, + Node_Select, + Node_SubmitButton, + Node_Text, + Node_TextInput, +) from .not_enterprise_plan_site import NotEnterprisePlanSite from .not_enterprise_plan_workspace import NotEnterprisePlanWorkspace +from .option_field import OptionField from .order import Order from .order_address import OrderAddress from .order_address_japan_type import OrderAddressJapanType from .order_address_type import OrderAddressType +from .order_billing_address import OrderBillingAddress +from .order_billing_address_japan_type import OrderBillingAddressJapanType +from .order_billing_address_type import OrderBillingAddressType from .order_customer_info import OrderCustomerInfo from .order_dispute_last_status import OrderDisputeLastStatus from .order_download_files_item import OrderDownloadFilesItem @@ -92,15 +143,26 @@ from .order_purchased_item_variant_image import OrderPurchasedItemVariantImage from .order_purchased_item_variant_image_file import OrderPurchasedItemVariantImageFile from .order_purchased_item_variant_image_file_variants_item import OrderPurchasedItemVariantImageFileVariantsItem +from .order_shipping_address import OrderShippingAddress +from .order_shipping_address_japan_type import OrderShippingAddressJapanType +from .order_shipping_address_type import OrderShippingAddressType from .order_status import OrderStatus from .order_totals import OrderTotals from .order_totals_extras_item import OrderTotalsExtrasItem from .order_totals_extras_item_type import OrderTotalsExtrasItemType from .page import Page +from .page_created_webhook import PageCreatedWebhook +from .page_created_webhook_payload import PageCreatedWebhookPayload +from .page_deleted_webhook import PageDeletedWebhook +from .page_deleted_webhook_payload import PageDeletedWebhookPayload from .page_list import PageList +from .page_metadata_updated_webhook import PageMetadataUpdatedWebhook +from .page_metadata_updated_webhook_payload import PageMetadataUpdatedWebhookPayload from .page_open_graph import PageOpenGraph from .page_seo import PageSeo from .pagination import Pagination +from .payload import Payload +from .payload_field_data import PayloadFieldData from .paypal_details import PaypalDetails from .product import Product from .product_and_sk_us import ProductAndSkUs @@ -111,11 +173,26 @@ from .publish_status import PublishStatus from .redirect import Redirect from .redirects import Redirects +from .reference_field import ReferenceField +from .reference_field_metadata import ReferenceFieldMetadata +from .reference_field_type import ReferenceFieldType from .registered_script_list import RegisteredScriptList +from .robots import Robots +from .robots_rules_item import RobotsRulesItem from .script_apply import ScriptApply from .script_apply_list import ScriptApplyList from .script_apply_location import ScriptApplyLocation from .scripts import Scripts +from .search_button_node import SearchButtonNode +from .search_button_node_write import SearchButtonNodeWrite +from .select import Select +from .select_node import SelectNode +from .select_node_choices_item import SelectNodeChoicesItem +from .select_node_write_choices_item import SelectNodeWriteChoicesItem +from .setting_change import SettingChange +from .setting_change_audit_log_item import SettingChangeAuditLogItem +from .single_locale_created_payload import SingleLocaleCreatedPayload +from .single_locale_created_payload_field_data import SingleLocaleCreatedPayloadFieldData from .site import Site from .site_activity_log_item import SiteActivityLogItem from .site_activity_log_item_event import SiteActivityLogItemEvent @@ -123,9 +200,14 @@ from .site_activity_log_item_user import SiteActivityLogItemUser from .site_activity_log_response import SiteActivityLogResponse from .site_data_collection_type import SiteDataCollectionType +from .site_membership import SiteMembership +from .site_membership_audit_log_item import SiteMembershipAuditLogItem +from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType from .site_plan import SitePlan from .site_plan_id import SitePlanId from .site_plan_name import SitePlanName +from .site_publish import SitePublish +from .site_publish_payload import SitePublishPayload from .sites import Sites from .sku import Sku from .sku_field_data import SkuFieldData @@ -139,31 +221,82 @@ from .sku_property_list import SkuPropertyList from .sku_property_list_enum_item import SkuPropertyListEnumItem from .sku_value_list import SkuValueList +from .static_field import StaticField +from .static_field_type import StaticFieldType from .stripe_card import StripeCard from .stripe_card_brand import StripeCardBrand from .stripe_card_expires import StripeCardExpires from .stripe_details import StripeDetails +from .submit_button_node import SubmitButtonNode +from .submit_button_node_write import SubmitButtonNodeWrite from .text import Text +from .text_input_node import TextInputNode +from .text_input_node_write import TextInputNodeWrite from .text_node import TextNode from .text_node_text import TextNodeText from .text_node_write import TextNodeWrite from .trigger_type import TriggerType -from .user import User -from .user_access_groups_item import UserAccessGroupsItem -from .user_access_groups_item_type import UserAccessGroupsItemType -from .user_data import UserData -from .user_data_data import UserDataData -from .user_limit_reached import UserLimitReached -from .user_list import UserList -from .user_status import UserStatus -from .users_not_enabled import UsersNotEnabled +from .updated_order import UpdatedOrder +from .user_access import UserAccess +from .user_access_audit_log_item import UserAccessAuditLogItem +from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType from .webhook import Webhook from .webhook_filter import WebhookFilter from .webhook_list import WebhookList +from .workspace_audit_log_item import ( + WorkspaceAuditLogItem, + WorkspaceAuditLogItem_CustomRole, + WorkspaceAuditLogItem_SiteMembership, + WorkspaceAuditLogItem_UserAccess, + WorkspaceAuditLogItem_WorkspaceInvitation, + WorkspaceAuditLogItem_WorkspaceMembership, + WorkspaceAuditLogItem_WorkspaceSetting, +) +from .workspace_audit_log_item_actor import WorkspaceAuditLogItemActor +from .workspace_audit_log_item_payload_setting_change_method import WorkspaceAuditLogItemPayloadSettingChangeMethod +from .workspace_audit_log_item_payload_site_membership_granular_access import ( + WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess, +) +from .workspace_audit_log_item_payload_site_membership_method import WorkspaceAuditLogItemPayloadSiteMembershipMethod +from .workspace_audit_log_item_payload_site_membership_site import WorkspaceAuditLogItemPayloadSiteMembershipSite +from .workspace_audit_log_item_payload_site_membership_target_user import ( + WorkspaceAuditLogItemPayloadSiteMembershipTargetUser, +) +from .workspace_audit_log_item_payload_site_membership_user_type import ( + WorkspaceAuditLogItemPayloadSiteMembershipUserType, +) +from .workspace_audit_log_item_payload_user_access_method import WorkspaceAuditLogItemPayloadUserAccessMethod +from .workspace_audit_log_item_payload_workspace_invitation_method import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod, +) +from .workspace_audit_log_item_payload_workspace_invitation_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, +) +from .workspace_audit_log_item_payload_workspace_invitation_target_users_item import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem, +) +from .workspace_audit_log_item_payload_workspace_invitation_user_type import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, +) +from .workspace_audit_log_item_payload_workspace_membership_method import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod, +) +from .workspace_audit_log_item_payload_workspace_membership_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, +) +from .workspace_audit_log_item_payload_workspace_membership_user_type import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType, +) +from .workspace_audit_log_item_workspace import WorkspaceAuditLogItemWorkspace +from .workspace_audit_log_response import WorkspaceAuditLogResponse +from .workspace_invitation import WorkspaceInvitation +from .workspace_invitation_audit_log_item import WorkspaceInvitationAuditLogItem +from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType +from .workspace_membership import WorkspaceMembership +from .workspace_membership_audit_log_item import WorkspaceMembershipAuditLogItem +from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType __all__ = [ - "AccessGroup", - "AccessGroupList", "Application", "Asset", "AssetFolder", @@ -181,6 +314,8 @@ "BulkCollectionItemFieldData", "Collection", "CollectionItem", + "CollectionItemChanged", + "CollectionItemCreated", "CollectionItemFieldData", "CollectionItemList", "CollectionItemListNoPagination", @@ -189,10 +324,31 @@ "CollectionItemPatchSingleFieldData", "CollectionItemPostSingle", "CollectionItemPostSingleFieldData", + "CollectionItemPublished", + "CollectionItemRemoved", + "CollectionItemRemovedPayload", + "CollectionItemRemovedPayloadFieldData", + "CollectionItemUnpublished", + "CollectionItemUnpublishedPayload", + "CollectionItemUnpublishedPayloadFieldData", "CollectionItemWithIdInput", "CollectionItemWithIdInputFieldData", "CollectionList", "CollectionListArrayItem", + "Comment", + "CommentPayload", + "CommentPayloadAuthor", + "CommentPayloadMentionedUsersItem", + "CommentReply", + "CommentReplyAuthor", + "CommentReplyList", + "CommentReplyListPagination", + "CommentReplyMentionedUsersItem", + "CommentThread", + "CommentThreadAuthor", + "CommentThreadList", + "CommentThreadListPagination", + "CommentThreadMentionedUsersItem", "Component", "ComponentDom", "ComponentInstanceNodePropertyOverridesWrite", @@ -202,20 +358,26 @@ "ComponentProperties", "ComponentProperty", "ComponentPropertyType", - "ConflictErrorBody", + "Conflict", "CustomCodeBlock", "CustomCodeBlockType", "CustomCodeHostedResponse", "CustomCodeInlineResponse", + "CustomRole", + "CustomRoleAuditLogItem", + "CustomRoleAuditLogItemEventSubType", "Dom", "Domain", "Domains", - "DuplicateUserEmail", "EcommerceSettings", "Error", "ErrorCode", "Field", + "FieldCreate", "FieldType", + "FieldValidations", + "FieldValidationsAdditionalProperties", + "FieldValidationsAdditionalPropertiesAdditionalProperties", "ForbiddenErrorBody", "Form", "FormField", @@ -225,26 +387,43 @@ "FormResponseSettings", "FormSubmission", "FormSubmissionList", + "FormSubmissionTrigger", + "FormSubmissionTriggerPayload", + "FormSubmissionTriggerPayloadSchemaItem", + "FormSubmissionTriggerPayloadSchemaItemFieldType", "ImageNode", "ImageNodeImage", "InvalidDomain", "InvalidScopes", "InventoryItem", "InventoryItemInventoryType", + "ItemsListItemsLiveRequestLastPublished", + "ItemsListItemsRequestLastPublished", "ListCustomCodeBlocks", "Locale", "Locales", + "Metadata", + "MetadataOptionsItem", + "NewOrder", "NoDomains", "Node", "Node_ComponentInstance", "Node_Image", + "Node_SearchButton", + "Node_Select", + "Node_SubmitButton", "Node_Text", + "Node_TextInput", "NotEnterprisePlanSite", "NotEnterprisePlanWorkspace", + "OptionField", "Order", "OrderAddress", "OrderAddressJapanType", "OrderAddressType", + "OrderBillingAddress", + "OrderBillingAddressJapanType", + "OrderBillingAddressType", "OrderCustomerInfo", "OrderDisputeLastStatus", "OrderDownloadFilesItem", @@ -255,15 +434,26 @@ "OrderPurchasedItemVariantImage", "OrderPurchasedItemVariantImageFile", "OrderPurchasedItemVariantImageFileVariantsItem", + "OrderShippingAddress", + "OrderShippingAddressJapanType", + "OrderShippingAddressType", "OrderStatus", "OrderTotals", "OrderTotalsExtrasItem", "OrderTotalsExtrasItemType", "Page", + "PageCreatedWebhook", + "PageCreatedWebhookPayload", + "PageDeletedWebhook", + "PageDeletedWebhookPayload", "PageList", + "PageMetadataUpdatedWebhook", + "PageMetadataUpdatedWebhookPayload", "PageOpenGraph", "PageSeo", "Pagination", + "Payload", + "PayloadFieldData", "PaypalDetails", "Product", "ProductAndSkUs", @@ -274,11 +464,26 @@ "PublishStatus", "Redirect", "Redirects", + "ReferenceField", + "ReferenceFieldMetadata", + "ReferenceFieldType", "RegisteredScriptList", + "Robots", + "RobotsRulesItem", "ScriptApply", "ScriptApplyList", "ScriptApplyLocation", "Scripts", + "SearchButtonNode", + "SearchButtonNodeWrite", + "Select", + "SelectNode", + "SelectNodeChoicesItem", + "SelectNodeWriteChoicesItem", + "SettingChange", + "SettingChangeAuditLogItem", + "SingleLocaleCreatedPayload", + "SingleLocaleCreatedPayloadFieldData", "Site", "SiteActivityLogItem", "SiteActivityLogItemEvent", @@ -286,9 +491,14 @@ "SiteActivityLogItemUser", "SiteActivityLogResponse", "SiteDataCollectionType", + "SiteMembership", + "SiteMembershipAuditLogItem", + "SiteMembershipAuditLogItemEventSubType", "SitePlan", "SitePlanId", "SitePlanName", + "SitePublish", + "SitePublishPayload", "Sites", "Sku", "SkuFieldData", @@ -302,25 +512,56 @@ "SkuPropertyList", "SkuPropertyListEnumItem", "SkuValueList", + "StaticField", + "StaticFieldType", "StripeCard", "StripeCardBrand", "StripeCardExpires", "StripeDetails", + "SubmitButtonNode", + "SubmitButtonNodeWrite", "Text", + "TextInputNode", + "TextInputNodeWrite", "TextNode", "TextNodeText", "TextNodeWrite", "TriggerType", - "User", - "UserAccessGroupsItem", - "UserAccessGroupsItemType", - "UserData", - "UserDataData", - "UserLimitReached", - "UserList", - "UserStatus", - "UsersNotEnabled", + "UpdatedOrder", + "UserAccess", + "UserAccessAuditLogItem", + "UserAccessAuditLogItemEventSubType", "Webhook", "WebhookFilter", "WebhookList", + "WorkspaceAuditLogItem", + "WorkspaceAuditLogItemActor", + "WorkspaceAuditLogItemPayloadSettingChangeMethod", + "WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess", + "WorkspaceAuditLogItemPayloadSiteMembershipMethod", + "WorkspaceAuditLogItemPayloadSiteMembershipSite", + "WorkspaceAuditLogItemPayloadSiteMembershipTargetUser", + "WorkspaceAuditLogItemPayloadSiteMembershipUserType", + "WorkspaceAuditLogItemPayloadUserAccessMethod", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType", + "WorkspaceAuditLogItemWorkspace", + "WorkspaceAuditLogItem_CustomRole", + "WorkspaceAuditLogItem_SiteMembership", + "WorkspaceAuditLogItem_UserAccess", + "WorkspaceAuditLogItem_WorkspaceInvitation", + "WorkspaceAuditLogItem_WorkspaceMembership", + "WorkspaceAuditLogItem_WorkspaceSetting", + "WorkspaceAuditLogResponse", + "WorkspaceInvitation", + "WorkspaceInvitationAuditLogItem", + "WorkspaceInvitationAuditLogItemEventSubType", + "WorkspaceMembership", + "WorkspaceMembershipAuditLogItem", + "WorkspaceMembershipAuditLogItemEventSubType", ] diff --git a/src/webflow/types/access_group.py b/src/webflow/types/access_group.py deleted file mode 100644 index fa2a418..0000000 --- a/src/webflow/types/access_group.py +++ /dev/null @@ -1,49 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ..core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic -import typing_extensions -from ..core.serialization import FieldMetadata -import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 - - -class AccessGroup(UniversalBaseModel): - id: typing.Optional[str] = pydantic.Field(default=None) - """ - Unique identifier for the Access Group - """ - - name: typing.Optional[str] = pydantic.Field(default=None) - """ - Name of the the Access Group - """ - - short_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="shortId")] = pydantic.Field( - default=None - ) - """ - Shortened unique identifier based on name, optimized for its use in the user’s JWT - """ - - slug: typing.Optional[str] = pydantic.Field(default=None) - """ - Shortened unique identifier based on name, optimized for human readability and public API use - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - The date the Access Group was created - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/webflow/types/access_group_list.py b/src/webflow/types/access_group_list.py deleted file mode 100644 index 0d5e140..0000000 --- a/src/webflow/types/access_group_list.py +++ /dev/null @@ -1,51 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ..core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic -import typing_extensions -from .access_group import AccessGroup -from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 - - -class AccessGroupList(UniversalBaseModel): - """ - The list access groups results - """ - - count: typing.Optional[float] = pydantic.Field(default=None) - """ - Number of access groups returned - """ - - limit: typing.Optional[float] = pydantic.Field(default=None) - """ - The limit specified in the request - """ - - offset: typing.Optional[float] = pydantic.Field(default=None) - """ - The offset specified for pagination - """ - - total: typing.Optional[float] = pydantic.Field(default=None) - """ - Total number of access groups in the collection - """ - - access_groups: typing_extensions.Annotated[ - typing.Optional[typing.List[AccessGroup]], FieldMetadata(alias="accessGroups") - ] = pydantic.Field(default=None) - """ - List of Site Access Groups - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/webflow/types/application.py b/src/webflow/types/application.py index ac819f0..b11f910 100644 --- a/src/webflow/types/application.py +++ b/src/webflow/types/application.py @@ -1,5 +1,41 @@ # This file was auto-generated by Fern from our API Definition. +from ..core.pydantic_utilities import UniversalBaseModel import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 -Application = typing.Optional[typing.Any] + +class Application(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for the Application + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + Application description provided by the developer + """ + + homepage: typing.Optional[str] = pydantic.Field(default=None) + """ + Application homepage URL provided by the developer + """ + + display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( + pydantic.Field(default=None) + ) + """ + Application name provided by the developer + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/asset.py b/src/webflow/types/asset.py index b67cefa..8ebad3b 100644 --- a/src/webflow/types/asset.py +++ b/src/webflow/types/asset.py @@ -11,6 +11,10 @@ class Asset(UniversalBaseModel): + """ + Asset details + """ + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for this asset @@ -49,9 +53,7 @@ class Asset(UniversalBaseModel): Original file name at the time of upload """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() """ Display name of the asset """ @@ -70,7 +72,11 @@ class Asset(UniversalBaseModel): Date the asset metadata was created """ - variants: typing.Optional[typing.List[AssetVariant]] = None + variants: typing.List[AssetVariant] = pydantic.Field() + """ + A list of [asset variants](https://help.webflow.com/hc/en-us/articles/33961378697107-Responsive-images) created by Webflow to serve your site responsively. + """ + alt_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="altText")] = pydantic.Field( default=None ) diff --git a/src/webflow/types/asset_variant.py b/src/webflow/types/asset_variant.py index 5278667..0ad16f1 100644 --- a/src/webflow/types/asset_variant.py +++ b/src/webflow/types/asset_variant.py @@ -2,40 +2,38 @@ from ..core.pydantic_utilities import UniversalBaseModel import typing_extensions -import typing from ..core.serialization import FieldMetadata import pydantic +import typing from ..core.pydantic_utilities import IS_PYDANTIC_V2 class AssetVariant(UniversalBaseModel): - hosted_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="hostedUrl")] = pydantic.Field( - default=None - ) + """ + Asset variant details + """ + + hosted_url: typing_extensions.Annotated[str, FieldMetadata(alias="hostedUrl")] = pydantic.Field() """ URL of where the asset variant is hosted """ - original_file_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="originalFileName")] = ( - pydantic.Field(default=None) - ) + original_file_name: typing_extensions.Annotated[str, FieldMetadata(alias="originalFileName")] = pydantic.Field() """ Original file name of the variant """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() """ Display name of the variant """ - format: typing.Optional[str] = pydantic.Field(default=None) + format: str = pydantic.Field() """ format of the variant """ - width: typing.Optional[int] = pydantic.Field(default=None) + width: int = pydantic.Field() """ Width in pixels """ @@ -45,7 +43,7 @@ class AssetVariant(UniversalBaseModel): Height in pixels """ - quality: typing.Optional[int] = pydantic.Field(default=None) + quality: int = pydantic.Field() """ Value between 0 and 100 representing the image quality """ diff --git a/src/webflow/types/assets.py b/src/webflow/types/assets.py index 380b0de..bd5f8ea 100644 --- a/src/webflow/types/assets.py +++ b/src/webflow/types/assets.py @@ -3,6 +3,7 @@ from ..core.pydantic_utilities import UniversalBaseModel import typing from .asset import Asset +from .pagination import Pagination from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -13,6 +14,7 @@ class Assets(UniversalBaseModel): """ assets: typing.Optional[typing.List[Asset]] = None + pagination: typing.Optional[Pagination] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/bulk_collection_item.py b/src/webflow/types/bulk_collection_item.py index 4d17d13..de8e770 100644 --- a/src/webflow/types/bulk_collection_item.py +++ b/src/webflow/types/bulk_collection_item.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. from ..core.pydantic_utilities import UniversalBaseModel +import typing import pydantic import typing_extensions -import typing from ..core.serialization import FieldMetadata from .bulk_collection_item_field_data import BulkCollectionItemFieldData from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -14,7 +14,7 @@ class BulkCollectionItem(UniversalBaseModel): The fields that define the schema for a given Item are based on the Collection that Item belongs to. Beyond the user defined fields, there are a handful of additional fields that are automatically created for all items """ - id: str = pydantic.Field() + id: typing.Optional[str] = pydantic.Field(default=None) """ Unique identifier for the Item """ diff --git a/src/webflow/types/collection.py b/src/webflow/types/collection.py index 81e0f90..561a535 100644 --- a/src/webflow/types/collection.py +++ b/src/webflow/types/collection.py @@ -3,8 +3,8 @@ from ..core.pydantic_utilities import UniversalBaseModel import pydantic import typing_extensions -import typing from ..core.serialization import FieldMetadata +import typing import datetime as dt from .field import Field from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -20,16 +20,12 @@ class Collection(UniversalBaseModel): Unique identifier for a Collection """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() """ Name given to the Collection """ - singular_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="singularName")] = ( - pydantic.Field(default=None) - ) + singular_name: typing_extensions.Annotated[str, FieldMetadata(alias="singularName")] = pydantic.Field() """ The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”) """ diff --git a/src/webflow/types/collection_item_changed.py b/src/webflow/types/collection_item_changed.py new file mode 100644 index 0000000..4484722 --- /dev/null +++ b/src/webflow/types/collection_item_changed.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .single_locale_created_payload import SingleLocaleCreatedPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemChanged(UniversalBaseModel): + """ + The Webhook payload for when a Collection Item is changed + """ + + trigger_type: typing_extensions.Annotated[ + typing.Literal["collection_item_changed"], FieldMetadata(alias="triggerType") + ] = pydantic.Field(default="collection_item_changed") + """ + The type of event that triggered the request + """ + + payload: SingleLocaleCreatedPayload + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_created.py b/src/webflow/types/collection_item_created.py new file mode 100644 index 0000000..bc6233c --- /dev/null +++ b/src/webflow/types/collection_item_created.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .single_locale_created_payload import SingleLocaleCreatedPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemCreated(UniversalBaseModel): + """ + The Webhook payload for when a Collection Item is created + """ + + trigger_type: typing_extensions.Annotated[ + typing.Literal["collection_item_created"], FieldMetadata(alias="triggerType") + ] = pydantic.Field(default="collection_item_created") + """ + The type of event that triggered the request + """ + + payload: SingleLocaleCreatedPayload + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_list_pagination.py b/src/webflow/types/collection_item_list_pagination.py index 394953b..5035868 100644 --- a/src/webflow/types/collection_item_list_pagination.py +++ b/src/webflow/types/collection_item_list_pagination.py @@ -7,17 +7,17 @@ class CollectionItemListPagination(UniversalBaseModel): - limit: typing.Optional[float] = pydantic.Field(default=None) + limit: typing.Optional[int] = pydantic.Field(default=None) """ The limit specified in the request """ - offset: typing.Optional[float] = pydantic.Field(default=None) + offset: typing.Optional[int] = pydantic.Field(default=None) """ The offset specified for pagination """ - total: typing.Optional[float] = pydantic.Field(default=None) + total: typing.Optional[int] = pydantic.Field(default=None) """ Total number of items in the collection """ diff --git a/src/webflow/types/collection_item_published.py b/src/webflow/types/collection_item_published.py new file mode 100644 index 0000000..c315f37 --- /dev/null +++ b/src/webflow/types/collection_item_published.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .payload import Payload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemPublished(UniversalBaseModel): + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[Payload] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_removed.py b/src/webflow/types/collection_item_removed.py new file mode 100644 index 0000000..fb09cd7 --- /dev/null +++ b/src/webflow/types/collection_item_removed.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .collection_item_removed_payload import CollectionItemRemovedPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemRemoved(UniversalBaseModel): + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[CollectionItemRemovedPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_removed_payload.py b/src/webflow/types/collection_item_removed_payload.py new file mode 100644 index 0000000..745cf3c --- /dev/null +++ b/src/webflow/types/collection_item_removed_payload.py @@ -0,0 +1,69 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt +from .collection_item_removed_payload_field_data import CollectionItemRemovedPayloadFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemRemovedPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + The ID of the collection item that was deleted + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The ID of the site + """ + + workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the workspace + """ + + collection_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="collectionId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the collection + """ + + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) + """ + Unique identifier of the CMS locale for this item + """ + + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + None + ) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None + field_data: typing_extensions.Annotated[ + typing.Optional[CollectionItemRemovedPayloadFieldData], FieldMetadata(alias="fieldData") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_data.py b/src/webflow/types/collection_item_removed_payload_field_data.py similarity index 71% rename from src/webflow/types/user_data.py rename to src/webflow/types/collection_item_removed_payload_field_data.py index 08e35ec..bca5629 100644 --- a/src/webflow/types/user_data.py +++ b/src/webflow/types/collection_item_removed_payload_field_data.py @@ -1,18 +1,14 @@ # This file was auto-generated by Fern from our API Definition. from ..core.pydantic_utilities import UniversalBaseModel -import typing -from .user_data_data import UserDataData from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing import pydantic -class UserData(UniversalBaseModel): - """ - An object containing the User's basic info and custom fields - """ - - data: typing.Optional[UserDataData] = None +class CollectionItemRemovedPayloadFieldData(UniversalBaseModel): + name: str + slug: str if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/collection_item_unpublished.py b/src/webflow/types/collection_item_unpublished.py new file mode 100644 index 0000000..ce23d7f --- /dev/null +++ b/src/webflow/types/collection_item_unpublished.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .collection_item_unpublished_payload import CollectionItemUnpublishedPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemUnpublished(UniversalBaseModel): + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[CollectionItemUnpublishedPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_unpublished_payload.py b/src/webflow/types/collection_item_unpublished_payload.py new file mode 100644 index 0000000..7250b24 --- /dev/null +++ b/src/webflow/types/collection_item_unpublished_payload.py @@ -0,0 +1,69 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt +from .collection_item_unpublished_payload_field_data import CollectionItemUnpublishedPayloadFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CollectionItemUnpublishedPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + The ID of the collection item that was unpublished + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The ID of the site + """ + + workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the workspace + """ + + collection_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="collectionId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the collection + """ + + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) + """ + Unique identifier of the CMS locale for this item + """ + + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + None + ) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None + field_data: typing_extensions.Annotated[ + typing.Optional[CollectionItemUnpublishedPayloadFieldData], FieldMetadata(alias="fieldData") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/collection_item_unpublished_payload_field_data.py b/src/webflow/types/collection_item_unpublished_payload_field_data.py new file mode 100644 index 0000000..8ae8719 --- /dev/null +++ b/src/webflow/types/collection_item_unpublished_payload_field_data.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class CollectionItemUnpublishedPayloadFieldData(UniversalBaseModel): + name: str + slug: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment.py b/src/webflow/types/comment.py new file mode 100644 index 0000000..b5df7e7 --- /dev/null +++ b/src/webflow/types/comment.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .comment_payload import CommentPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Comment(UniversalBaseModel): + """ + The Webhook payload for when a comment thread or reply is made on a Site + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[CommentPayload] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_payload.py b/src/webflow/types/comment_payload.py new file mode 100644 index 0000000..c6b6a38 --- /dev/null +++ b/src/webflow/types/comment_payload.py @@ -0,0 +1,114 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .comment_payload_author import CommentPayloadAuthor +from .comment_payload_mentioned_users_item import CommentPayloadMentionedUsersItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CommentPayload(UniversalBaseModel): + """ + The comment webhook payload contains data for the thread and for replies. Check the type to determine if the payload is for a thread or a reply. The webhook payload may be delayed by up to 5 minutes. + """ + + thread_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="threadId")] = pydantic.Field( + default=None + ) + """ + Unique identifier for the comment thread + """ + + comment_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="commentId")] = pydantic.Field( + default=None + ) + """ + Unique identifier for the comment reply + """ + + type: typing.Optional[str] = pydantic.Field(default=None) + """ + The type of comment payload + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The site unique identifier + """ + + page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = pydantic.Field( + default=None + ) + """ + The page unique identifier + """ + + locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="localeId")] = pydantic.Field( + default=None + ) + """ + The locale unique identifier + """ + + item_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="itemId")] = pydantic.Field( + default=None + ) + """ + The item unique identifier + """ + + breakpoint: typing.Optional[str] = pydantic.Field(default=None) + """ + The breakpoint the comment was left on + """ + + url: typing.Optional[str] = pydantic.Field(default=None) + """ + The URL of the page the comment was left on + """ + + content: str = pydantic.Field() + """ + The content of the comment reply + """ + + is_resolved: typing_extensions.Annotated[bool, FieldMetadata(alias="isResolved")] = pydantic.Field() + """ + Boolean determining if the comment thread is resolved + """ + + author: CommentPayloadAuthor + mentioned_users: typing_extensions.Annotated[ + typing.List[CommentPayloadMentionedUsersItem], FieldMetadata(alias="mentionedUsers") + ] = pydantic.Field() + """ + List of mentioned users. This is an empty array until email notifications are sent, which can take up to 5 minutes after the comment is created. + """ + + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) + """ + The date the item was created + """ + + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last updated + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_access_groups_item.py b/src/webflow/types/comment_payload_author.py similarity index 50% rename from src/webflow/types/user_access_groups_item.py rename to src/webflow/types/comment_payload_author.py index 55ab6b3..04c9ba8 100644 --- a/src/webflow/types/user_access_groups_item.py +++ b/src/webflow/types/comment_payload_author.py @@ -1,27 +1,27 @@ # This file was auto-generated by Fern from our API Definition. from ..core.pydantic_utilities import UniversalBaseModel -import typing +import typing_extensions +from ..core.serialization import FieldMetadata import pydantic -from .user_access_groups_item_type import UserAccessGroupsItemType from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing -class UserAccessGroupsItem(UniversalBaseModel): +class CommentPayloadAuthor(UniversalBaseModel): + user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() """ - Access group slugs and types + The unique identifier of the author """ - slug: typing.Optional[str] = pydantic.Field(default=None) + email: str = pydantic.Field() """ - Access group identifier for APIs + Email of the author """ - type: typing.Optional[UserAccessGroupsItemType] = pydantic.Field(default=None) + name: str = pydantic.Field() """ - The type of access group based on how it was assigned to the user. - * `admin` - Assigned to the user via API or in the designer - * `ecommerce` - Assigned to the user via an ecommerce purchase + Name of the author """ if IS_PYDANTIC_V2: diff --git a/src/webflow/types/comment_payload_mentioned_users_item.py b/src/webflow/types/comment_payload_mentioned_users_item.py new file mode 100644 index 0000000..7a63d83 --- /dev/null +++ b/src/webflow/types/comment_payload_mentioned_users_item.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentPayloadMentionedUsersItem(UniversalBaseModel): + user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() + """ + The unique identifier of the mentioned user + """ + + email: str = pydantic.Field() + """ + Email of the user + """ + + name: str = pydantic.Field() + """ + Name of the User + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_reply.py b/src/webflow/types/comment_reply.py new file mode 100644 index 0000000..1017249 --- /dev/null +++ b/src/webflow/types/comment_reply.py @@ -0,0 +1,89 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import typing +from .comment_reply_author import CommentReplyAuthor +from .comment_reply_mentioned_users_item import CommentReplyMentionedUsersItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CommentReply(UniversalBaseModel): + """ + A comment thread represents a conversation between users on a specific page. Each comment thread has a unique identifier and can contain multiple comments. + """ + + id: str = pydantic.Field() + """ + Unique identifier for the comment thread + """ + + comment_id: typing_extensions.Annotated[str, FieldMetadata(alias="commentId")] = pydantic.Field() + """ + The comment reply unique identifier + """ + + site_id: typing_extensions.Annotated[str, FieldMetadata(alias="siteId")] = pydantic.Field() + """ + The site unique identifier + """ + + page_id: typing_extensions.Annotated[str, FieldMetadata(alias="pageId")] = pydantic.Field() + """ + The page unique identifier + """ + + locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="localeId")] = pydantic.Field( + default=None + ) + """ + The locale unique identifier + """ + + breakpoint: str = pydantic.Field() + """ + The breakpoint the comment was left on + """ + + content: str = pydantic.Field() + """ + The content of the comment reply + """ + + is_resolved: typing_extensions.Annotated[bool, FieldMetadata(alias="isResolved")] = pydantic.Field() + """ + Boolean determining if the comment thread is resolved + """ + + author: CommentReplyAuthor + mentioned_users: typing_extensions.Annotated[ + typing.Optional[typing.List[CommentReplyMentionedUsersItem]], FieldMetadata(alias="mentionedUsers") + ] = pydantic.Field(default=None) + """ + List of mentioned users is an empty array until email notifications are sent. + """ + + last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The date the item was last updated + """ + + created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( + default=None + ) + """ + The date the item was created + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_reply_author.py b/src/webflow/types/comment_reply_author.py new file mode 100644 index 0000000..7509b7e --- /dev/null +++ b/src/webflow/types/comment_reply_author.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentReplyAuthor(UniversalBaseModel): + id: str = pydantic.Field() + """ + The unique identifier of the author + """ + + email: str = pydantic.Field() + """ + Email of the author + """ + + name: str = pydantic.Field() + """ + Name of the author + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_reply_list.py b/src/webflow/types/comment_reply_list.py new file mode 100644 index 0000000..c382932 --- /dev/null +++ b/src/webflow/types/comment_reply_list.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .comment_reply import CommentReply +from .comment_reply_list_pagination import CommentReplyListPagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class CommentReplyList(UniversalBaseModel): + """ + A list of comment replies. + """ + + comments: typing.List[CommentReply] + pagination: CommentReplyListPagination + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_reply_list_pagination.py b/src/webflow/types/comment_reply_list_pagination.py new file mode 100644 index 0000000..48fd7ed --- /dev/null +++ b/src/webflow/types/comment_reply_list_pagination.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentReplyListPagination(UniversalBaseModel): + limit: int = pydantic.Field() + """ + The limit specified in the request (default 100) + """ + + offset: int = pydantic.Field() + """ + The offset specified for pagination + """ + + total: int = pydantic.Field() + """ + Total number of comment replies + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_reply_mentioned_users_item.py b/src/webflow/types/comment_reply_mentioned_users_item.py new file mode 100644 index 0000000..12324d9 --- /dev/null +++ b/src/webflow/types/comment_reply_mentioned_users_item.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentReplyMentionedUsersItem(UniversalBaseModel): + id: str = pydantic.Field() + """ + The unique identifier of the mentioned user + """ + + email: str = pydantic.Field() + """ + Email of the user + """ + + name: str = pydantic.Field() + """ + Name of the User + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_thread.py b/src/webflow/types/comment_thread.py new file mode 100644 index 0000000..0694916 --- /dev/null +++ b/src/webflow/types/comment_thread.py @@ -0,0 +1,92 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import typing +from .comment_thread_author import CommentThreadAuthor +from .comment_thread_mentioned_users_item import CommentThreadMentionedUsersItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CommentThread(UniversalBaseModel): + """ + A comment thread represents a conversation between users on a specific page. Each comment thread has a unique identifier and can contain multiple comments. Retrieve comment replies using the replies API endpoint. + """ + + id: str = pydantic.Field() + """ + Unique identifier for the comment thread + """ + + site_id: typing_extensions.Annotated[str, FieldMetadata(alias="siteId")] = pydantic.Field() + """ + The site unique identifier + """ + + page_id: typing_extensions.Annotated[str, FieldMetadata(alias="pageId")] = pydantic.Field() + """ + The page unique identifier + """ + + locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="localeId")] = pydantic.Field( + default=None + ) + """ + The locale unique identifier + """ + + item_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="itemId")] = pydantic.Field( + default=None + ) + """ + The item unique identifier + """ + + breakpoint: str = pydantic.Field() + """ + The breakpoint the comment was left on + """ + + url: str = pydantic.Field() + """ + The URL of the page the comment was left on + """ + + content: str = pydantic.Field() + """ + The content of the comment reply + """ + + is_resolved: typing_extensions.Annotated[bool, FieldMetadata(alias="isResolved")] = pydantic.Field() + """ + Boolean determining if the comment thread is resolved + """ + + author: CommentThreadAuthor + mentioned_users: typing_extensions.Annotated[ + typing.List[CommentThreadMentionedUsersItem], FieldMetadata(alias="mentionedUsers") + ] = pydantic.Field() + """ + List of mentioned users. This is an empty array until email notifications are sent, which can take up to 5 minutes after the comment is created. + """ + + created_on: typing_extensions.Annotated[str, FieldMetadata(alias="createdOn")] = pydantic.Field() + """ + The date the item was created + """ + + last_updated: typing_extensions.Annotated[str, FieldMetadata(alias="lastUpdated")] = pydantic.Field() + """ + The date the item was last updated + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_thread_author.py b/src/webflow/types/comment_thread_author.py new file mode 100644 index 0000000..c2f1b1e --- /dev/null +++ b/src/webflow/types/comment_thread_author.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentThreadAuthor(UniversalBaseModel): + user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() + """ + The unique identifier of the author + """ + + email: str = pydantic.Field() + """ + Email of the author + """ + + name: str = pydantic.Field() + """ + Name of the author + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_thread_list.py b/src/webflow/types/comment_thread_list.py new file mode 100644 index 0000000..f46e6bd --- /dev/null +++ b/src/webflow/types/comment_thread_list.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .comment_thread import CommentThread +from .comment_thread_list_pagination import CommentThreadListPagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class CommentThreadList(UniversalBaseModel): + """ + A list of comment threads on the site. Contains the content of the first reply. + """ + + comments: typing.List[CommentThread] + pagination: CommentThreadListPagination + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_thread_list_pagination.py b/src/webflow/types/comment_thread_list_pagination.py new file mode 100644 index 0000000..6b1dccb --- /dev/null +++ b/src/webflow/types/comment_thread_list_pagination.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentThreadListPagination(UniversalBaseModel): + limit: int = pydantic.Field() + """ + The limit specified in the request (default 100) + """ + + offset: int = pydantic.Field() + """ + The offset specified for pagination + """ + + total: int = pydantic.Field() + """ + Total number of comment threads + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/comment_thread_mentioned_users_item.py b/src/webflow/types/comment_thread_mentioned_users_item.py new file mode 100644 index 0000000..f9a20df --- /dev/null +++ b/src/webflow/types/comment_thread_mentioned_users_item.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class CommentThreadMentionedUsersItem(UniversalBaseModel): + user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() + """ + The unique identifier of the mentioned user + """ + + email: str = pydantic.Field() + """ + Email of the user + """ + + name: str = pydantic.Field() + """ + Name of the User + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/component_dom.py b/src/webflow/types/component_dom.py index 3f76c81..2f70fc4 100644 --- a/src/webflow/types/component_dom.py +++ b/src/webflow/types/component_dom.py @@ -12,7 +12,7 @@ class ComponentDom(UniversalBaseModel): """ - The Component DOM schema represents the content structure of a component. Similar to Page DOM, it captures various content nodes and their associated attributes, but specifically for a component's structure. Each node has a unique identifier and can contain text, images, or nested component instances. + The Component DOM schema represents the content structure of a component. Similar to Page DOM, it captures various content nodes and their associated attributes, but specifically for a component's structure. Each node has a unique identifier and can contain text, images, select or text inputs, submit buttons, or nested component instances. """ component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = ( diff --git a/src/webflow/types/component_node.py b/src/webflow/types/component_node.py index fa5f69d..6735289 100644 --- a/src/webflow/types/component_node.py +++ b/src/webflow/types/component_node.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. from ..core.pydantic_utilities import UniversalBaseModel -import typing import pydantic import typing_extensions from ..core.serialization import FieldMetadata +import typing from .component_property import ComponentProperty from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -14,21 +14,19 @@ class ComponentNode(UniversalBaseModel): Represents a component instance within the DOM. It contains details about the component instance, such as its type and properties. """ - id: typing.Optional[str] = pydantic.Field(default=None) + id: str = pydantic.Field() """ - Node UUID + The unique identifier of the component instance node """ - component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = ( - pydantic.Field(default=None) - ) + component_id: typing_extensions.Annotated[str, FieldMetadata(alias="componentId")] = pydantic.Field() """ - Component ID + The unique identifier of the component """ property_overrides: typing_extensions.Annotated[ - typing.Optional[typing.List[ComponentProperty]], FieldMetadata(alias="propertyOverrides") - ] = pydantic.Field(default=None) + typing.List[ComponentProperty], FieldMetadata(alias="propertyOverrides") + ] = pydantic.Field() """ List of component properties with overrides for a component instance. """ diff --git a/src/webflow/types/users_not_enabled.py b/src/webflow/types/conflict.py similarity index 63% rename from src/webflow/types/users_not_enabled.py rename to src/webflow/types/conflict.py index 05df7dc..30b9809 100644 --- a/src/webflow/types/users_not_enabled.py +++ b/src/webflow/types/conflict.py @@ -2,4 +2,4 @@ import typing -UsersNotEnabled = typing.Optional[typing.Any] +Conflict = typing.Optional[typing.Any] diff --git a/src/webflow/types/conflict_error_body.py b/src/webflow/types/conflict_error_body.py deleted file mode 100644 index 2ec15f8..0000000 --- a/src/webflow/types/conflict_error_body.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -from .duplicate_user_email import DuplicateUserEmail -from .user_limit_reached import UserLimitReached - -ConflictErrorBody = typing.Union[DuplicateUserEmail, UserLimitReached] diff --git a/src/webflow/types/custom_role.py b/src/webflow/types/custom_role.py new file mode 100644 index 0000000..f8c9440 --- /dev/null +++ b/src/webflow/types/custom_role.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class CustomRole(UniversalBaseModel): + role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( + default=None + ) + """ + The name of the custom role + """ + + previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( + pydantic.Field(default=None) + ) + """ + The previous name of the custom role + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/custom_role_audit_log_item.py b/src/webflow/types/custom_role_audit_log_item.py new file mode 100644 index 0000000..336aa26 --- /dev/null +++ b/src/webflow/types/custom_role_audit_log_item.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType +from ..core.serialization import FieldMetadata +from .custom_role import CustomRole +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class CustomRoleAuditLogItem(UniversalBaseModel): + event_sub_type: typing_extensions.Annotated[ + typing.Optional[CustomRoleAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[CustomRole] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/custom_role_audit_log_item_event_sub_type.py b/src/webflow/types/custom_role_audit_log_item_event_sub_type.py new file mode 100644 index 0000000..38d177b --- /dev/null +++ b/src/webflow/types/custom_role_audit_log_item_event_sub_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +CustomRoleAuditLogItemEventSubType = typing.Union[ + typing.Literal["role_created", "role_updated", "role_deleted"], typing.Any +] diff --git a/src/webflow/types/dom.py b/src/webflow/types/dom.py index ce15a6a..45c87b4 100644 --- a/src/webflow/types/dom.py +++ b/src/webflow/types/dom.py @@ -7,6 +7,7 @@ import pydantic from .node import Node from .pagination import Pagination +import datetime as dt from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -22,8 +23,21 @@ class Dom(UniversalBaseModel): Page ID """ + branch_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="branchId")] = pydantic.Field( + default=None + ) + """ + The unique identifier of a [specific page branch.](https://help.webflow.com/hc/en-us/articles/33961355506195-Page-branching) + """ + nodes: typing.Optional[typing.List[Node]] = None pagination: typing.Optional[Pagination] = None + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( + pydantic.Field(default=None) + ) + """ + The date the page dom was most recently updated + """ if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/field.py b/src/webflow/types/field.py index 40233a9..9543092 100644 --- a/src/webflow/types/field.py +++ b/src/webflow/types/field.py @@ -6,6 +6,7 @@ from ..core.serialization import FieldMetadata import typing from .field_type import FieldType +from .field_validations import FieldValidations from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -53,6 +54,11 @@ class Field(UniversalBaseModel): Additional text to help anyone filling out this field """ + validations: typing.Optional[FieldValidations] = pydantic.Field(default=None) + """ + The validations for the field + """ + if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 else: diff --git a/src/webflow/types/field_create.py b/src/webflow/types/field_create.py new file mode 100644 index 0000000..1c9cf61 --- /dev/null +++ b/src/webflow/types/field_create.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .static_field import StaticField +from .option_field import OptionField +from .reference_field import ReferenceField + +FieldCreate = typing.Union[StaticField, OptionField, ReferenceField] diff --git a/src/webflow/types/field_type.py b/src/webflow/types/field_type.py index 6318a3d..e3495ce 100644 --- a/src/webflow/types/field_type.py +++ b/src/webflow/types/field_type.py @@ -8,15 +8,19 @@ "DateTime", "Email", "ExtFileRef", + "File", "Image", "Link", "MultiImage", + "MultiReference", "Number", + "Option", "Phone", "PlainText", + "Reference", "RichText", "Switch", - "Video", + "VideoLink", ], typing.Any, ] diff --git a/src/webflow/types/field_validations.py b/src/webflow/types/field_validations.py new file mode 100644 index 0000000..ca58a0b --- /dev/null +++ b/src/webflow/types/field_validations.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .field_validations_additional_properties import FieldValidationsAdditionalProperties +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class FieldValidations(UniversalBaseModel): + """ + The validations for the field + """ + + additional_properties: typing_extensions.Annotated[ + typing.Optional[FieldValidationsAdditionalProperties], FieldMetadata(alias="additionalProperties") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/field_validations_additional_properties.py b/src/webflow/types/field_validations_additional_properties.py new file mode 100644 index 0000000..ba31807 --- /dev/null +++ b/src/webflow/types/field_validations_additional_properties.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from .field_validations_additional_properties_additional_properties import ( + FieldValidationsAdditionalPropertiesAdditionalProperties, +) + +FieldValidationsAdditionalProperties = typing.Union[ + str, float, bool, int, FieldValidationsAdditionalPropertiesAdditionalProperties +] diff --git a/src/webflow/types/field_validations_additional_properties_additional_properties.py b/src/webflow/types/field_validations_additional_properties_additional_properties.py new file mode 100644 index 0000000..aa6c548 --- /dev/null +++ b/src/webflow/types/field_validations_additional_properties_additional_properties.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class FieldValidationsAdditionalPropertiesAdditionalProperties(UniversalBaseModel): + additional_properties: typing_extensions.Annotated[ + typing.Optional[typing.Any], FieldMetadata(alias="additionalProperties") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/forbidden_error_body.py b/src/webflow/types/forbidden_error_body.py index f580ad2..5530c7a 100644 --- a/src/webflow/types/forbidden_error_body.py +++ b/src/webflow/types/forbidden_error_body.py @@ -2,6 +2,6 @@ import typing from .invalid_scopes import InvalidScopes -from .users_not_enabled import UsersNotEnabled +from .not_enterprise_plan_site import NotEnterprisePlanSite -ForbiddenErrorBody = typing.Union[InvalidScopes, UsersNotEnabled] +ForbiddenErrorBody = typing.Union[InvalidScopes, NotEnterprisePlanSite] diff --git a/src/webflow/types/form_submission_trigger.py b/src/webflow/types/form_submission_trigger.py new file mode 100644 index 0000000..82f1eaf --- /dev/null +++ b/src/webflow/types/form_submission_trigger.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .form_submission_trigger_payload import FormSubmissionTriggerPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class FormSubmissionTrigger(UniversalBaseModel): + """ + The Webhook payload for when a form is submitted + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[FormSubmissionTriggerPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_submission_trigger_payload.py b/src/webflow/types/form_submission_trigger_payload.py new file mode 100644 index 0000000..f192a9f --- /dev/null +++ b/src/webflow/types/form_submission_trigger_payload.py @@ -0,0 +1,74 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .form_submission_trigger_payload_schema_item import FormSubmissionTriggerPayloadSchemaItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class FormSubmissionTriggerPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + The name of the form + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The ID of the site that the form was submitted from + """ + + data: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) + """ + The data submitted in the form + """ + + schema_: typing_extensions.Annotated[ + typing.Optional[typing.List[FormSubmissionTriggerPayloadSchemaItem]], FieldMetadata(alias="schema") + ] = pydantic.Field(default=None) + """ + A list of fields from the submitted form + """ + + submitted_at: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="submittedAt")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp the form was submitted + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + the ID of the event + """ + + form_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="formId")] = pydantic.Field( + default=None + ) + """ + The ID of the form submission + """ + + form_element_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="formElementId")] = ( + pydantic.Field(default=None) + ) + """ + The uniqueID of the Form element + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_submission_trigger_payload_schema_item.py b/src/webflow/types/form_submission_trigger_payload_schema_item.py new file mode 100644 index 0000000..014322f --- /dev/null +++ b/src/webflow/types/form_submission_trigger_payload_schema_item.py @@ -0,0 +1,41 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .form_submission_trigger_payload_schema_item_field_type import FormSubmissionTriggerPayloadSchemaItemFieldType +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class FormSubmissionTriggerPayloadSchemaItem(UniversalBaseModel): + field_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="fieldName")] = pydantic.Field( + default=None + ) + """ + Form field name + """ + + field_type: typing_extensions.Annotated[ + typing.Optional[FormSubmissionTriggerPayloadSchemaItemFieldType], FieldMetadata(alias="fieldType") + ] = pydantic.Field(default=None) + """ + Form field type + """ + + field_element_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="fieldElementId")] = ( + pydantic.Field(default=None) + ) + """ + Element ID of the Form Field + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/form_submission_trigger_payload_schema_item_field_type.py b/src/webflow/types/form_submission_trigger_payload_schema_item_field_type.py new file mode 100644 index 0000000..0ab97d1 --- /dev/null +++ b/src/webflow/types/form_submission_trigger_payload_schema_item_field_type.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +FormSubmissionTriggerPayloadSchemaItemFieldType = typing.Union[ + typing.Literal["FormTextInput", "FormTextarea", "FormCheckboxInput", "FormRadioInput", "FormFileUploadInput"], + typing.Any, +] diff --git a/src/webflow/types/image_node.py b/src/webflow/types/image_node.py index 2351cea..c4e7eac 100644 --- a/src/webflow/types/image_node.py +++ b/src/webflow/types/image_node.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. from ..core.pydantic_utilities import UniversalBaseModel -import typing import pydantic from .image_node_image import ImageNodeImage +import typing from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -12,12 +12,16 @@ class ImageNode(UniversalBaseModel): Represents an image within the DOM. It contains details about the image, such as its alternative text (alt) for accessibility and an asset identifier for fetching the actual image resource. Additional attributes can be associated with the image for styling or other purposes. """ - id: typing.Optional[str] = pydantic.Field(default=None) + id: str = pydantic.Field() """ Node UUID """ - image: typing.Optional[ImageNodeImage] = None + image: ImageNodeImage = pydantic.Field() + """ + The image details of the node + """ + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) """ The custom attributes of the node diff --git a/src/webflow/types/image_node_image.py b/src/webflow/types/image_node_image.py index 2ef819f..f8d9379 100644 --- a/src/webflow/types/image_node_image.py +++ b/src/webflow/types/image_node_image.py @@ -9,6 +9,10 @@ class ImageNodeImage(UniversalBaseModel): + """ + The image details of the node + """ + alt: typing.Optional[str] = None asset_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="assetId")] = None diff --git a/src/webflow/types/items_list_items_live_request_last_published.py b/src/webflow/types/items_list_items_live_request_last_published.py new file mode 100644 index 0000000..31aab15 --- /dev/null +++ b/src/webflow/types/items_list_items_live_request_last_published.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import datetime as dt +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ItemsListItemsLiveRequestLastPublished(UniversalBaseModel): + lte: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + Filter items last published before this date + """ + + gte: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + Filter items last published after this date + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/items_list_items_request_last_published.py b/src/webflow/types/items_list_items_request_last_published.py new file mode 100644 index 0000000..bf4505d --- /dev/null +++ b/src/webflow/types/items_list_items_request_last_published.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import datetime as dt +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ItemsListItemsRequestLastPublished(UniversalBaseModel): + lte: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + Filter items last published before this date + """ + + gte: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + Filter items last published after this date + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/metadata.py b/src/webflow/types/metadata.py new file mode 100644 index 0000000..1c9caa7 --- /dev/null +++ b/src/webflow/types/metadata.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .metadata_options_item import MetadataOptionsItem +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Metadata(UniversalBaseModel): + """ + The metadata for the Option field. + """ + + options: typing.List[MetadataOptionsItem] = pydantic.Field() + """ + The option values for the Option field. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/metadata_options_item.py b/src/webflow/types/metadata_options_item.py new file mode 100644 index 0000000..91eb360 --- /dev/null +++ b/src/webflow/types/metadata_options_item.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class MetadataOptionsItem(UniversalBaseModel): + """ + A single option value for the Option field. + """ + + name: str = pydantic.Field() + """ + The name of the option + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + The unique identifier of the option + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/new_order.py b/src/webflow/types/new_order.py new file mode 100644 index 0000000..c156c65 --- /dev/null +++ b/src/webflow/types/new_order.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .order import Order +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class NewOrder(UniversalBaseModel): + """ + The Webhook payload for when a new order is created + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[Order] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/node.py b/src/webflow/types/node.py index cd0942f..6ec64b9 100644 --- a/src/webflow/types/node.py +++ b/src/webflow/types/node.py @@ -10,6 +10,7 @@ import typing_extensions from ..core.serialization import FieldMetadata from .component_property import ComponentProperty +from .select_node_choices_item import SelectNodeChoicesItem class Node_Text(UniversalBaseModel): @@ -18,8 +19,8 @@ class Node_Text(UniversalBaseModel): """ type: typing.Literal["text"] = "text" - id: typing.Optional[str] = None - text: typing.Optional[TextNodeText] = None + id: str + text: TextNodeText attributes: typing.Optional[typing.Dict[str, str]] = None if IS_PYDANTIC_V2: @@ -38,8 +39,8 @@ class Node_Image(UniversalBaseModel): """ type: typing.Literal["image"] = "image" - id: typing.Optional[str] = None - image: typing.Optional[ImageNodeImage] = None + id: str + image: ImageNodeImage attributes: typing.Optional[typing.Dict[str, str]] = None if IS_PYDANTIC_V2: @@ -58,11 +59,11 @@ class Node_ComponentInstance(UniversalBaseModel): """ type: typing.Literal["component-instance"] = "component-instance" - id: typing.Optional[str] = None - component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = None + id: str + component_id: typing_extensions.Annotated[str, FieldMetadata(alias="componentId")] property_overrides: typing_extensions.Annotated[ - typing.Optional[typing.List[ComponentProperty]], FieldMetadata(alias="propertyOverrides") - ] = None + typing.List[ComponentProperty], FieldMetadata(alias="propertyOverrides") + ] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 @@ -74,4 +75,87 @@ class Config: extra = pydantic.Extra.allow -Node = typing.Union[Node_Text, Node_Image, Node_ComponentInstance] +class Node_TextInput(UniversalBaseModel): + """ + A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. + """ + + type: typing.Literal["text-input"] = "text-input" + id: str + placeholder: str + attributes: typing.Optional[typing.Dict[str, str]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class Node_Select(UniversalBaseModel): + """ + A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. + """ + + type: typing.Literal["select"] = "select" + id: str + choices: typing.List[SelectNodeChoicesItem] + attributes: typing.Optional[typing.Dict[str, str]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class Node_SubmitButton(UniversalBaseModel): + """ + A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. + """ + + type: typing.Literal["submit-button"] = "submit-button" + id: str + value: str + waiting_text: typing_extensions.Annotated[str, FieldMetadata(alias="waitingText")] + attributes: typing.Optional[typing.Dict[str, str]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class Node_SearchButton(UniversalBaseModel): + """ + A generic representation of a content element within the Document Object Model (DOM). Each node has a unique identifier and a specific type that determines its content structure and attributes. + """ + + type: typing.Literal["search-button"] = "search-button" + id: str + value: str + attributes: typing.Optional[typing.Dict[str, str]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +Node = typing.Union[ + Node_Text, Node_Image, Node_ComponentInstance, Node_TextInput, Node_Select, Node_SubmitButton, Node_SearchButton +] diff --git a/src/webflow/types/option_field.py b/src/webflow/types/option_field.py new file mode 100644 index 0000000..7f7c6d5 --- /dev/null +++ b/src/webflow/types/option_field.py @@ -0,0 +1,58 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .metadata import Metadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class OptionField(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for a Field + """ + + is_editable: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEditable")] = pydantic.Field( + default=None + ) + """ + Define whether the field is editable + """ + + is_required: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isRequired")] = pydantic.Field( + default=None + ) + """ + define whether a field is required in a collection + """ + + type: typing.Literal["Option"] = pydantic.Field(default="Option") + """ + The [Option field type](/data/reference/field-types-item-values#option) + """ + + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() + """ + The name of a field + """ + + help_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="helpText")] = pydantic.Field( + default=None + ) + """ + Additional text to help anyone filling out this field + """ + + metadata: Metadata + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order.py b/src/webflow/types/order.py index d45b1de..2b2844c 100644 --- a/src/webflow/types/order.py +++ b/src/webflow/types/order.py @@ -10,6 +10,8 @@ from .order_dispute_last_status import OrderDisputeLastStatus from .order_price import OrderPrice from .order_address import OrderAddress +from .order_shipping_address import OrderShippingAddress +from .order_billing_address import OrderBillingAddress from .order_customer_info import OrderCustomerInfo from .order_purchased_item import OrderPurchasedItem from .stripe_details import StripeDetails @@ -119,14 +121,14 @@ class Order(UniversalBaseModel): """ shipping_address: typing_extensions.Annotated[ - typing.Optional[OrderAddress], FieldMetadata(alias="shippingAddress") + typing.Optional[OrderShippingAddress], FieldMetadata(alias="shippingAddress") ] = pydantic.Field(default=None) """ The shipping address """ billing_address: typing_extensions.Annotated[ - typing.Optional[OrderAddress], FieldMetadata(alias="billingAddress") + typing.Optional[OrderBillingAddress], FieldMetadata(alias="billingAddress") ] = pydantic.Field(default=None) """ The billing address diff --git a/src/webflow/types/order_billing_address.py b/src/webflow/types/order_billing_address.py new file mode 100644 index 0000000..75e87c6 --- /dev/null +++ b/src/webflow/types/order_billing_address.py @@ -0,0 +1,78 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .order_billing_address_type import OrderBillingAddressType +import pydantic +import typing_extensions +from .order_billing_address_japan_type import OrderBillingAddressJapanType +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class OrderBillingAddress(UniversalBaseModel): + """ + The billing address + """ + + type: typing.Optional[OrderBillingAddressType] = pydantic.Field(default=None) + """ + The type of the order address (billing or shipping) + """ + + japan_type: typing_extensions.Annotated[ + typing.Optional[OrderBillingAddressJapanType], FieldMetadata(alias="japanType") + ] = pydantic.Field(default=None) + """ + Represents a Japan-only address format. This field will only appear on orders placed from Japan. + """ + + addressee: typing.Optional[str] = pydantic.Field(default=None) + """ + Display name on the address + """ + + line_1: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line1")] = pydantic.Field( + default=None + ) + """ + The first line of the address + """ + + line_2: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line2")] = pydantic.Field( + default=None + ) + """ + The second line of the address + """ + + city: typing.Optional[str] = pydantic.Field(default=None) + """ + The city of the address. + """ + + state: typing.Optional[str] = pydantic.Field(default=None) + """ + The state or province of the address + """ + + country: typing.Optional[str] = pydantic.Field(default=None) + """ + The country of the address + """ + + postal_code: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="postalCode")] = pydantic.Field( + default=None + ) + """ + The postal code of the address + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_billing_address_japan_type.py b/src/webflow/types/order_billing_address_japan_type.py new file mode 100644 index 0000000..8c983bb --- /dev/null +++ b/src/webflow/types/order_billing_address_japan_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +OrderBillingAddressJapanType = typing.Union[typing.Literal["kana", "kanji"], typing.Any] diff --git a/src/webflow/types/order_billing_address_type.py b/src/webflow/types/order_billing_address_type.py new file mode 100644 index 0000000..6b03d6e --- /dev/null +++ b/src/webflow/types/order_billing_address_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +OrderBillingAddressType = typing.Union[typing.Literal["shipping", "billing"], typing.Any] diff --git a/src/webflow/types/order_shipping_address.py b/src/webflow/types/order_shipping_address.py new file mode 100644 index 0000000..5c62f00 --- /dev/null +++ b/src/webflow/types/order_shipping_address.py @@ -0,0 +1,78 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .order_shipping_address_type import OrderShippingAddressType +import pydantic +import typing_extensions +from .order_shipping_address_japan_type import OrderShippingAddressJapanType +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class OrderShippingAddress(UniversalBaseModel): + """ + The shipping address + """ + + type: typing.Optional[OrderShippingAddressType] = pydantic.Field(default=None) + """ + The type of the order address (billing or shipping) + """ + + japan_type: typing_extensions.Annotated[ + typing.Optional[OrderShippingAddressJapanType], FieldMetadata(alias="japanType") + ] = pydantic.Field(default=None) + """ + Represents a Japan-only address format. This field will only appear on orders placed from Japan. + """ + + addressee: typing.Optional[str] = pydantic.Field(default=None) + """ + Display name on the address + """ + + line_1: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line1")] = pydantic.Field( + default=None + ) + """ + The first line of the address + """ + + line_2: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line2")] = pydantic.Field( + default=None + ) + """ + The second line of the address + """ + + city: typing.Optional[str] = pydantic.Field(default=None) + """ + The city of the address. + """ + + state: typing.Optional[str] = pydantic.Field(default=None) + """ + The state or province of the address + """ + + country: typing.Optional[str] = pydantic.Field(default=None) + """ + The country of the address + """ + + postal_code: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="postalCode")] = pydantic.Field( + default=None + ) + """ + The postal code of the address + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/order_shipping_address_japan_type.py b/src/webflow/types/order_shipping_address_japan_type.py new file mode 100644 index 0000000..b5b548e --- /dev/null +++ b/src/webflow/types/order_shipping_address_japan_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +OrderShippingAddressJapanType = typing.Union[typing.Literal["kana", "kanji"], typing.Any] diff --git a/src/webflow/types/order_shipping_address_type.py b/src/webflow/types/order_shipping_address_type.py new file mode 100644 index 0000000..467ccbd --- /dev/null +++ b/src/webflow/types/order_shipping_address_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +OrderShippingAddressType = typing.Union[typing.Literal["shipping", "billing"], typing.Any] diff --git a/src/webflow/types/page.py b/src/webflow/types/page.py index 56b32d3..51346a0 100644 --- a/src/webflow/types/page.py +++ b/src/webflow/types/page.py @@ -80,7 +80,7 @@ class Page(UniversalBaseModel): default=None ) """ - Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching) + Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching). Pages that are already branches cannot be branched again. """ is_branch: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isBranch")] = pydantic.Field( @@ -90,11 +90,11 @@ class Page(UniversalBaseModel): Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) """ - is_members_only: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isMembersOnly")] = ( - pydantic.Field(default=None) + branch_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="branchId")] = pydantic.Field( + default=None ) """ - Indicates whether the Page is restricted by [Memberships Controls](https://university.webflow.com/lesson/webflow-memberships-overview#how-to-manage-page-restrictions) + If the Page is a Branch of another Page, this is the ID of the Branch """ seo: typing.Optional[PageSeo] = pydantic.Field(default=None) diff --git a/src/webflow/types/page_created_webhook.py b/src/webflow/types/page_created_webhook.py new file mode 100644 index 0000000..60ef73e --- /dev/null +++ b/src/webflow/types/page_created_webhook.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .page_created_webhook_payload import PageCreatedWebhookPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class PageCreatedWebhook(UniversalBaseModel): + """ + The Webhook payload for when a Page is created + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[PageCreatedWebhookPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_created_webhook_payload.py b/src/webflow/types/page_created_webhook_payload.py new file mode 100644 index 0000000..e986315 --- /dev/null +++ b/src/webflow/types/page_created_webhook_payload.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class PageCreatedWebhookPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = None + page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = None + page_title: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageTitle")] = None + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None + published_path: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="publishedPath")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_deleted_webhook.py b/src/webflow/types/page_deleted_webhook.py new file mode 100644 index 0000000..5894078 --- /dev/null +++ b/src/webflow/types/page_deleted_webhook.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .page_deleted_webhook_payload import PageDeletedWebhookPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class PageDeletedWebhook(UniversalBaseModel): + """ + The Webhook payload for when a Page is deleted + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[PageDeletedWebhookPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_deleted_webhook_payload.py b/src/webflow/types/page_deleted_webhook_payload.py new file mode 100644 index 0000000..5d09458 --- /dev/null +++ b/src/webflow/types/page_deleted_webhook_payload.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class PageDeletedWebhookPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = None + page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = None + page_title: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageTitle")] = None + deleted_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="deletedOn")] = None + published_path: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="publishedPath")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_metadata_updated_webhook.py b/src/webflow/types/page_metadata_updated_webhook.py new file mode 100644 index 0000000..1bcb1e1 --- /dev/null +++ b/src/webflow/types/page_metadata_updated_webhook.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .page_metadata_updated_webhook_payload import PageMetadataUpdatedWebhookPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class PageMetadataUpdatedWebhook(UniversalBaseModel): + """ + The Webhook payload for when a Page's metadata is updated + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[PageMetadataUpdatedWebhookPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/page_metadata_updated_webhook_payload.py b/src/webflow/types/page_metadata_updated_webhook_payload.py new file mode 100644 index 0000000..a75b703 --- /dev/null +++ b/src/webflow/types/page_metadata_updated_webhook_payload.py @@ -0,0 +1,30 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class PageMetadataUpdatedWebhookPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = None + page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = None + page_title: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageTitle")] = None + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + published_path: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="publishedPath")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/pagination.py b/src/webflow/types/pagination.py index aa38c46..82e650c 100644 --- a/src/webflow/types/pagination.py +++ b/src/webflow/types/pagination.py @@ -11,17 +11,17 @@ class Pagination(UniversalBaseModel): Pagination object """ - limit: typing.Optional[float] = pydantic.Field(default=None) + limit: typing.Optional[int] = pydantic.Field(default=None) """ The limit used for pagination """ - offset: typing.Optional[float] = pydantic.Field(default=None) + offset: typing.Optional[int] = pydantic.Field(default=None) """ The offset used for pagination """ - total: typing.Optional[float] = pydantic.Field(default=None) + total: typing.Optional[int] = pydantic.Field(default=None) """ The total number of records """ diff --git a/src/webflow/types/payload.py b/src/webflow/types/payload.py new file mode 100644 index 0000000..a608741 --- /dev/null +++ b/src/webflow/types/payload.py @@ -0,0 +1,67 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import datetime as dt +from .payload_field_data import PayloadFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Payload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + The ID of the collection item that was unpublished + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The ID of the site + """ + + workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the workspace + """ + + collection_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="collectionId")] = ( + pydantic.Field(default=None) + ) + """ + The ID of the collection + """ + + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) + """ + Unique identifier of the CMS locale for this item + """ + + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + None + ) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None + field_data: typing_extensions.Annotated[typing.Optional[PayloadFieldData], FieldMetadata(alias="fieldData")] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/payload_field_data.py b/src/webflow/types/payload_field_data.py new file mode 100644 index 0000000..6fa4fc5 --- /dev/null +++ b/src/webflow/types/payload_field_data.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class PayloadFieldData(UniversalBaseModel): + name: str + slug: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/product_field_data.py b/src/webflow/types/product_field_data.py index e58b83d..e907159 100644 --- a/src/webflow/types/product_field_data.py +++ b/src/webflow/types/product_field_data.py @@ -43,9 +43,9 @@ class ProductFieldData(UniversalBaseModel): Variant types to include in SKUs """ - categories: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + category: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ - The categories your product belongs to. + The category your product belongs to. """ tax_category: typing_extensions.Annotated[ diff --git a/src/webflow/types/reference_field.py b/src/webflow/types/reference_field.py new file mode 100644 index 0000000..3c75552 --- /dev/null +++ b/src/webflow/types/reference_field.py @@ -0,0 +1,62 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .reference_field_type import ReferenceFieldType +from .reference_field_metadata import ReferenceFieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class ReferenceField(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for a Field + """ + + is_editable: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEditable")] = pydantic.Field( + default=None + ) + """ + Define whether the field is editable + """ + + is_required: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isRequired")] = pydantic.Field( + default=None + ) + """ + define whether a field is required in a collection + """ + + type: ReferenceFieldType = pydantic.Field() + """ + Choose these appropriate field type for your collection data + """ + + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() + """ + The name of a field + """ + + help_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="helpText")] = pydantic.Field( + default=None + ) + """ + Additional text to help anyone filling out this field + """ + + metadata: ReferenceFieldMetadata = pydantic.Field() + """ + The collectionId for the referenced collection. Only applicable for Reference and MultiReference fields. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/reference_field_metadata.py b/src/webflow/types/reference_field_metadata.py new file mode 100644 index 0000000..164c4a6 --- /dev/null +++ b/src/webflow/types/reference_field_metadata.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class ReferenceFieldMetadata(UniversalBaseModel): + """ + The collectionId for the referenced collection. Only applicable for Reference and MultiReference fields. + """ + + collection_id: typing_extensions.Annotated[str, FieldMetadata(alias="collectionId")] = pydantic.Field() + """ + The unique identifier of the collection + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/reference_field_type.py b/src/webflow/types/reference_field_type.py new file mode 100644 index 0000000..b80f3e1 --- /dev/null +++ b/src/webflow/types/reference_field_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ReferenceFieldType = typing.Union[typing.Literal["MultiReference", "Reference"], typing.Any] diff --git a/src/webflow/types/registered_script_list.py b/src/webflow/types/registered_script_list.py index ddfff8d..e9d8a01 100644 --- a/src/webflow/types/registered_script_list.py +++ b/src/webflow/types/registered_script_list.py @@ -5,6 +5,7 @@ import typing from .custom_code_hosted_response import CustomCodeHostedResponse from ..core.serialization import FieldMetadata +from .pagination import Pagination from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic @@ -17,6 +18,7 @@ class RegisteredScriptList(UniversalBaseModel): registered_scripts: typing_extensions.Annotated[ typing.Optional[typing.List[CustomCodeHostedResponse]], FieldMetadata(alias="registeredScripts") ] = None + pagination: typing.Optional[Pagination] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/robots.py b/src/webflow/types/robots.py new file mode 100644 index 0000000..7489660 --- /dev/null +++ b/src/webflow/types/robots.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .robots_rules_item import RobotsRulesItem +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Robots(UniversalBaseModel): + """ + The robots.txt file for a given site + """ + + rules: typing.Optional[typing.List[RobotsRulesItem]] = pydantic.Field(default=None) + """ + List of rules for user agents. + """ + + sitemap: typing.Optional[str] = pydantic.Field(default=None) + """ + URL to the sitemap. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/robots_rules_item.py b/src/webflow/types/robots_rules_item.py new file mode 100644 index 0000000..048f239 --- /dev/null +++ b/src/webflow/types/robots_rules_item.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class RobotsRulesItem(UniversalBaseModel): + user_agent: typing_extensions.Annotated[str, FieldMetadata(alias="userAgent")] = pydantic.Field() + """ + The user agent the rules apply to. + """ + + allows: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + """ + List of paths allowed for this user agent. + """ + + disallows: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + """ + List of paths disallowed for this user agent. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/search_button_node.py b/src/webflow/types/search_button_node.py new file mode 100644 index 0000000..091b06c --- /dev/null +++ b/src/webflow/types/search_button_node.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SearchButtonNode(UniversalBaseModel): + """ + Represents search button elements within the DOM. It contains the text of the button. Additional attributes can be associated with the text for styling or other purposes. + """ + + id: str = pydantic.Field() + """ + Node UUID + """ + + value: str = pydantic.Field() + """ + The text content of the search button. + """ + + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + The custom attributes of the node + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/search_button_node_write.py b/src/webflow/types/search_button_node_write.py new file mode 100644 index 0000000..15c5daf --- /dev/null +++ b/src/webflow/types/search_button_node_write.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class SearchButtonNodeWrite(UniversalBaseModel): + """ + Update a search button node + """ + + node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() + """ + Node UUID + """ + + value: str = pydantic.Field() + """ + The text content of the search button. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/select.py b/src/webflow/types/select.py new file mode 100644 index 0000000..7208091 --- /dev/null +++ b/src/webflow/types/select.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +import typing +from .select_node_write_choices_item import SelectNodeWriteChoicesItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class Select(UniversalBaseModel): + """ + Update choices on a select node + """ + + node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() + """ + Node UUID + """ + + choices: typing.List[SelectNodeWriteChoicesItem] = pydantic.Field() + """ + The list of choices to set on the select node. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/select_node.py b/src/webflow/types/select_node.py new file mode 100644 index 0000000..f8cc21f --- /dev/null +++ b/src/webflow/types/select_node.py @@ -0,0 +1,37 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing +from .select_node_choices_item import SelectNodeChoicesItem +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SelectNode(UniversalBaseModel): + """ + Represents select elements within the DOM. It contains the list of choices in the select. Additional attributes can be associated with the text for styling or other purposes. + """ + + id: str = pydantic.Field() + """ + Node UUID + """ + + choices: typing.List[SelectNodeChoicesItem] = pydantic.Field() + """ + The list of choices in this select node. + """ + + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + The custom attributes of the node + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/select_node_choices_item.py b/src/webflow/types/select_node_choices_item.py new file mode 100644 index 0000000..cd210b1 --- /dev/null +++ b/src/webflow/types/select_node_choices_item.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class SelectNodeChoicesItem(UniversalBaseModel): + value: str = pydantic.Field() + """ + The value of the choice when selected. + """ + + text: str = pydantic.Field() + """ + The text to display for the choice. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/select_node_write_choices_item.py b/src/webflow/types/select_node_write_choices_item.py new file mode 100644 index 0000000..4346fef --- /dev/null +++ b/src/webflow/types/select_node_write_choices_item.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class SelectNodeWriteChoicesItem(UniversalBaseModel): + value: str = pydantic.Field() + """ + The value of the choice when selected. + """ + + text: str = pydantic.Field() + """ + The text to display for the choice. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/setting_change.py b/src/webflow/types/setting_change.py new file mode 100644 index 0000000..8bbbb06 --- /dev/null +++ b/src/webflow/types/setting_change.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import typing_extensions +from ..core.serialization import FieldMetadata +from .workspace_audit_log_item_payload_setting_change_method import WorkspaceAuditLogItemPayloadSettingChangeMethod +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class SettingChange(UniversalBaseModel): + setting: typing.Optional[typing.Literal["ai_toggle"]] = None + previous_value: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousValue")] = None + value: typing.Optional[str] = None + method: typing.Optional[WorkspaceAuditLogItemPayloadSettingChangeMethod] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/setting_change_audit_log_item.py b/src/webflow/types/setting_change_audit_log_item.py new file mode 100644 index 0000000..62b8579 --- /dev/null +++ b/src/webflow/types/setting_change_audit_log_item.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +from .setting_change import SettingChange +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class SettingChangeAuditLogItem(UniversalBaseModel): + event_sub_type: typing_extensions.Annotated[ + typing.Optional[typing.Literal["setting_updated"]], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[SettingChange] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/single_locale_created_payload.py b/src/webflow/types/single_locale_created_payload.py new file mode 100644 index 0000000..9293d8c --- /dev/null +++ b/src/webflow/types/single_locale_created_payload.py @@ -0,0 +1,57 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import typing +import datetime as dt +from .single_locale_created_payload_field_data import SingleLocaleCreatedPayloadFieldData +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SingleLocaleCreatedPayload(UniversalBaseModel): + id: str = pydantic.Field() + """ + Unique identifier for the Item + """ + + workspace_id: typing_extensions.Annotated[str, FieldMetadata(alias="workspaceId")] = pydantic.Field() + """ + Unique identifier of the workspace + """ + + site_id: typing_extensions.Annotated[str, FieldMetadata(alias="siteId")] = pydantic.Field() + """ + Unique identifier of the site + """ + + collection_id: typing_extensions.Annotated[str, FieldMetadata(alias="collectionId")] = pydantic.Field() + """ + Unique identifier of the collection + """ + + cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( + pydantic.Field(default=None) + ) + """ + Unique identifier of the CMS locale for this item + """ + + last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( + None + ) + last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None + is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None + is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None + field_data: typing_extensions.Annotated[SingleLocaleCreatedPayloadFieldData, FieldMetadata(alias="fieldData")] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/single_locale_created_payload_field_data.py b/src/webflow/types/single_locale_created_payload_field_data.py new file mode 100644 index 0000000..b412ef9 --- /dev/null +++ b/src/webflow/types/single_locale_created_payload_field_data.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class SingleLocaleCreatedPayloadFieldData(UniversalBaseModel): + name: str + slug: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_membership.py b/src/webflow/types/site_membership.py new file mode 100644 index 0000000..5ff933a --- /dev/null +++ b/src/webflow/types/site_membership.py @@ -0,0 +1,56 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .workspace_audit_log_item_payload_site_membership_site import WorkspaceAuditLogItemPayloadSiteMembershipSite +import typing_extensions +from .workspace_audit_log_item_payload_site_membership_target_user import ( + WorkspaceAuditLogItemPayloadSiteMembershipTargetUser, +) +from ..core.serialization import FieldMetadata +from .workspace_audit_log_item_payload_site_membership_method import WorkspaceAuditLogItemPayloadSiteMembershipMethod +from .workspace_audit_log_item_payload_site_membership_user_type import ( + WorkspaceAuditLogItemPayloadSiteMembershipUserType, +) +import pydantic +from .workspace_audit_log_item_payload_site_membership_granular_access import ( + WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess, +) +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SiteMembership(UniversalBaseModel): + site: typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipSite] = None + target_user: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipTargetUser], FieldMetadata(alias="targetUser") + ] = None + method: typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipMethod] = None + user_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipUserType], FieldMetadata(alias="userType") + ] = None + role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( + default=None + ) + """ + The name of the role that was assigned to the user + """ + + previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( + pydantic.Field(default=None) + ) + """ + The previous role that the user had + """ + + granular_access: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess], FieldMetadata(alias="granularAccess") + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_membership_audit_log_item.py b/src/webflow/types/site_membership_audit_log_item.py new file mode 100644 index 0000000..d24ee9f --- /dev/null +++ b/src/webflow/types/site_membership_audit_log_item.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType +from ..core.serialization import FieldMetadata +from .site_membership import SiteMembership +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class SiteMembershipAuditLogItem(UniversalBaseModel): + event_sub_type: typing_extensions.Annotated[ + typing.Optional[SiteMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[SiteMembership] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_membership_audit_log_item_event_sub_type.py b/src/webflow/types/site_membership_audit_log_item_event_sub_type.py new file mode 100644 index 0000000..ff26017 --- /dev/null +++ b/src/webflow/types/site_membership_audit_log_item_event_sub_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +SiteMembershipAuditLogItemEventSubType = typing.Union[ + typing.Literal["user_added", "user_removed", "user_role_updated", "user_granular_access_updated"], typing.Any +] diff --git a/src/webflow/types/site_publish.py b/src/webflow/types/site_publish.py new file mode 100644 index 0000000..518178e --- /dev/null +++ b/src/webflow/types/site_publish.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .site_publish_payload import SitePublishPayload +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SitePublish(UniversalBaseModel): + """ + The Webhook payload for when a Site is published + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[SitePublishPayload] = pydantic.Field(default=None) + """ + The payload of data sent from Webflow + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/site_publish_payload.py b/src/webflow/types/site_publish_payload.py new file mode 100644 index 0000000..f44882e --- /dev/null +++ b/src/webflow/types/site_publish_payload.py @@ -0,0 +1,50 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SitePublishPayload(UniversalBaseModel): + """ + The payload of data sent from Webflow + """ + + site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( + default=None + ) + """ + The ID of the site that was published + """ + + published_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="publishedOn")] = ( + pydantic.Field(default=None) + ) + """ + The timestamp of the publish event + """ + + domains: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + """ + The domains that were published + """ + + published_by: typing_extensions.Annotated[ + typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]], FieldMetadata(alias="publishedBy") + ] = pydantic.Field(default=None) + """ + The name andID of the user who published the site + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/sku_field_data.py b/src/webflow/types/sku_field_data.py index e20efdb..c7540d8 100644 --- a/src/webflow/types/sku_field_data.py +++ b/src/webflow/types/sku_field_data.py @@ -10,6 +10,7 @@ from .sku_field_data_compare_at_price import SkuFieldDataCompareAtPrice from .sku_field_data_ec_sku_billing_method import SkuFieldDataEcSkuBillingMethod from .sku_field_data_ec_sku_subscription_plan import SkuFieldDataEcSkuSubscriptionPlan +from .sku_property_list import SkuPropertyList from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -43,20 +44,35 @@ class SkuFieldData(UniversalBaseModel): ec_sku_billing_method: typing_extensions.Annotated[ typing.Optional[SkuFieldDataEcSkuBillingMethod], FieldMetadata(alias="ec-sku-billing-method") - ] = None + ] = pydantic.Field(default=None) + """ + [Billing method](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#billing-methods)for the SKU + """ + ec_sku_subscription_plan: typing_extensions.Annotated[ typing.Optional[SkuFieldDataEcSkuSubscriptionPlan], FieldMetadata(alias="ec-sku-subscription-plan") - ] = None - track_inventory: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="track-inventory")] = ( - pydantic.Field(default=None) + ] = pydantic.Field(default=None) + """ + [Subscription plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) for the SKU + """ + + main_image: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="main-image")] = pydantic.Field( + default=None ) """ - A boolean indicating whether inventory for this product should be tracked. + The URL for the main image of the SKU + """ + + sku: typing.Optional[str] = pydantic.Field(default=None) + """ + A unique identifier for the SKU """ - quantity: typing.Optional[float] = pydantic.Field(default=None) + sku_properties: typing_extensions.Annotated[ + typing.Optional[typing.List[SkuPropertyList]], FieldMetadata(alias="sku-properties") + ] = pydantic.Field(default=None) """ - Quantity of SKU that will be tracked as items are ordered. + The properties of the SKU """ if IS_PYDANTIC_V2: diff --git a/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py b/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py index 24c85a7..ed2e484 100644 --- a/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py +++ b/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py @@ -9,6 +9,10 @@ class SkuFieldDataEcSkuSubscriptionPlan(UniversalBaseModel): + """ + [Subscription plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) for the SKU + """ + interval: typing.Optional[SkuFieldDataEcSkuSubscriptionPlanInterval] = pydantic.Field(default=None) """ Interval of subscription renewal diff --git a/src/webflow/types/sku_field_data_price.py b/src/webflow/types/sku_field_data_price.py index 45ff611..cb31f4a 100644 --- a/src/webflow/types/sku_field_data_price.py +++ b/src/webflow/types/sku_field_data_price.py @@ -21,6 +21,11 @@ class SkuFieldDataPrice(UniversalBaseModel): Currency of Item """ + currency: typing.Optional[str] = pydantic.Field(default=None) + """ + Currency of Item (alternative representation) + """ + if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 else: diff --git a/src/webflow/types/static_field.py b/src/webflow/types/static_field.py new file mode 100644 index 0000000..c6e6162 --- /dev/null +++ b/src/webflow/types/static_field.py @@ -0,0 +1,56 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .static_field_type import StaticFieldType +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class StaticField(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) + """ + Unique identifier for a Field + """ + + is_editable: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEditable")] = pydantic.Field( + default=None + ) + """ + Define whether the field is editable + """ + + is_required: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isRequired")] = pydantic.Field( + default=None + ) + """ + define whether a field is required in a collection + """ + + type: StaticFieldType = pydantic.Field() + """ + Choose these appropriate field type for your collection data + """ + + display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() + """ + The name of a field + """ + + help_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="helpText")] = pydantic.Field( + default=None + ) + """ + Additional text to help anyone filling out this field + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/resources/collections/resources/fields/types/field_create_type.py b/src/webflow/types/static_field_type.py similarity index 82% rename from src/webflow/resources/collections/resources/fields/types/field_create_type.py rename to src/webflow/types/static_field_type.py index c8ec44b..e7cadf0 100644 --- a/src/webflow/resources/collections/resources/fields/types/field_create_type.py +++ b/src/webflow/types/static_field_type.py @@ -2,12 +2,11 @@ import typing -FieldCreateType = typing.Union[ +StaticFieldType = typing.Union[ typing.Literal[ "Color", "DateTime", "Email", - "ExtFileRef", "File", "Image", "Link", @@ -17,7 +16,7 @@ "PlainText", "RichText", "Switch", - "Video", + "VideoLink", ], typing.Any, ] diff --git a/src/webflow/types/submit_button_node.py b/src/webflow/types/submit_button_node.py new file mode 100644 index 0000000..25ba646 --- /dev/null +++ b/src/webflow/types/submit_button_node.py @@ -0,0 +1,43 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SubmitButtonNode(UniversalBaseModel): + """ + Represents submit button elements within the DOM. It contains the text and waiting text of the button. Additional attributes can be associated with the text for styling or other purposes. + """ + + id: str = pydantic.Field() + """ + Node UUID + """ + + value: str = pydantic.Field() + """ + The text content of the submit button. + """ + + waiting_text: typing_extensions.Annotated[str, FieldMetadata(alias="waitingText")] = pydantic.Field() + """ + The text to show while the form is submitting. + """ + + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + The custom attributes of the node + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/submit_button_node_write.py b/src/webflow/types/submit_button_node_write.py new file mode 100644 index 0000000..6233215 --- /dev/null +++ b/src/webflow/types/submit_button_node_write.py @@ -0,0 +1,40 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class SubmitButtonNodeWrite(UniversalBaseModel): + """ + Update a submit button node + """ + + node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() + """ + Node UUID + """ + + value: typing.Optional[str] = pydantic.Field(default=None) + """ + The text content of the submit button. + """ + + waiting_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="waitingText")] = ( + pydantic.Field(default=None) + ) + """ + The text to show while the form is submitting. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/text.py b/src/webflow/types/text.py index 18f8501..913d5d1 100644 --- a/src/webflow/types/text.py +++ b/src/webflow/types/text.py @@ -7,6 +7,10 @@ class Text(UniversalBaseModel): + """ + The text content of the node + """ + html: typing.Optional[str] = pydantic.Field(default=None) """ The HTML content of the text node. diff --git a/src/webflow/types/text_input_node.py b/src/webflow/types/text_input_node.py new file mode 100644 index 0000000..7146e15 --- /dev/null +++ b/src/webflow/types/text_input_node.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import pydantic +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class TextInputNode(UniversalBaseModel): + """ + Represents text input and textarea elements within the DOM. It contains the placeholder text in the input. Additional attributes can be associated with the text for styling or other purposes. + """ + + id: str = pydantic.Field() + """ + Node UUID + """ + + placeholder: str = pydantic.Field() + """ + The placeholder text of the input node + """ + + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) + """ + The custom attributes of the node + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/text_input_node_write.py b/src/webflow/types/text_input_node_write.py new file mode 100644 index 0000000..6ea8e98 --- /dev/null +++ b/src/webflow/types/text_input_node_write.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +from ..core.serialization import FieldMetadata +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class TextInputNodeWrite(UniversalBaseModel): + """ + Update placeholder text on a text input node + """ + + node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() + """ + Node UUID + """ + + placeholder: str = pydantic.Field() + """ + The placeholder text of the input node + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/text_node.py b/src/webflow/types/text_node.py index 1e16717..aa15d4b 100644 --- a/src/webflow/types/text_node.py +++ b/src/webflow/types/text_node.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. from ..core.pydantic_utilities import UniversalBaseModel -import typing import pydantic from .text_node_text import TextNodeText +import typing from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -12,12 +12,16 @@ class TextNode(UniversalBaseModel): Represents text content within the DOM. It contains both the raw text and its HTML representation. Additional attributes can be associated with the text for styling or other purposes. """ - id: typing.Optional[str] = pydantic.Field(default=None) + id: str = pydantic.Field() """ Node UUID """ - text: typing.Optional[TextNodeText] = None + text: TextNodeText = pydantic.Field() + """ + The text content of the node + """ + attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) """ The custom attributes of the node diff --git a/src/webflow/types/text_node_text.py b/src/webflow/types/text_node_text.py index 895dc0b..5add2f0 100644 --- a/src/webflow/types/text_node_text.py +++ b/src/webflow/types/text_node_text.py @@ -7,6 +7,10 @@ class TextNodeText(UniversalBaseModel): + """ + The text content of the node + """ + html: typing.Optional[str] = pydantic.Field(default=None) """ The HTML content of the text node. diff --git a/src/webflow/types/trigger_type.py b/src/webflow/types/trigger_type.py index e12b650..5b9e821 100644 --- a/src/webflow/types/trigger_type.py +++ b/src/webflow/types/trigger_type.py @@ -12,13 +12,12 @@ "ecomm_new_order", "ecomm_order_changed", "ecomm_inventory_changed", - "user_account_added", - "user_account_updated", - "user_account_deleted", "collection_item_created", "collection_item_changed", "collection_item_deleted", + "collection_item_published", "collection_item_unpublished", + "comment_created", ], typing.Any, ] diff --git a/src/webflow/types/updated_order.py b/src/webflow/types/updated_order.py new file mode 100644 index 0000000..a3fc241 --- /dev/null +++ b/src/webflow/types/updated_order.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from ..core.serialization import FieldMetadata +import pydantic +from .order import Order +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class UpdatedOrder(UniversalBaseModel): + """ + The Webhook payload for when an order is updated + """ + + trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( + pydantic.Field(default=None) + ) + """ + The type of event that triggered the request + """ + + payload: typing.Optional[Order] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user.py b/src/webflow/types/user.py deleted file mode 100644 index a27a063..0000000 --- a/src/webflow/types/user.py +++ /dev/null @@ -1,81 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ..core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic -import typing_extensions -from ..core.serialization import FieldMetadata -import datetime as dt -from .user_status import UserStatus -from .user_access_groups_item import UserAccessGroupsItem -from .user_data import UserData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 - - -class User(UniversalBaseModel): - """ - The fields that define the schema for a given Item are based on the Collection that Item belongs to. Beyond the user defined fields, there are a handful of additional fields that are automatically created for all items - """ - - id: typing.Optional[str] = pydantic.Field(default=None) - """ - Unique identifier for the User - """ - - is_email_verified: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEmailVerified")] = ( - pydantic.Field(default=None) - ) - """ - Shows whether the user has verified their email address - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The timestamp the user was updated - """ - - invited_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="invitedOn")] = ( - pydantic.Field(default=None) - ) - """ - The timestamp the user was invited - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - The timestamp the user was created - """ - - last_login: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastLogin")] = ( - pydantic.Field(default=None) - ) - """ - The timestamp the user was logged in - """ - - status: typing.Optional[UserStatus] = pydantic.Field(default=None) - """ - The status of the user - """ - - access_groups: typing_extensions.Annotated[ - typing.Optional[typing.List[UserAccessGroupsItem]], FieldMetadata(alias="accessGroups") - ] = pydantic.Field(default=None) - """ - Access groups the user belongs to - """ - - data: typing.Optional[UserData] = None - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_access.py b/src/webflow/types/user_access.py new file mode 100644 index 0000000..7c869dd --- /dev/null +++ b/src/webflow/types/user_access.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .workspace_audit_log_item_payload_user_access_method import WorkspaceAuditLogItemPayloadUserAccessMethod +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class UserAccess(UniversalBaseModel): + method: typing.Optional[WorkspaceAuditLogItemPayloadUserAccessMethod] = None + location: typing.Optional[str] = pydantic.Field(default=None) + """ + The geolocation based on the logged IP address + """ + + ip_address: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="ipAddress")] = pydantic.Field( + default=None + ) + """ + The captured IP address of the user + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_access_audit_log_item.py b/src/webflow/types/user_access_audit_log_item.py new file mode 100644 index 0000000..b94e6a7 --- /dev/null +++ b/src/webflow/types/user_access_audit_log_item.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType +from ..core.serialization import FieldMetadata +from .user_access import UserAccess +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class UserAccessAuditLogItem(UniversalBaseModel): + event_sub_type: typing_extensions.Annotated[ + typing.Optional[UserAccessAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[UserAccess] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_access_audit_log_item_event_sub_type.py b/src/webflow/types/user_access_audit_log_item_event_sub_type.py new file mode 100644 index 0000000..382f247 --- /dev/null +++ b/src/webflow/types/user_access_audit_log_item_event_sub_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +UserAccessAuditLogItemEventSubType = typing.Union[typing.Literal["login", "logout"], typing.Any] diff --git a/src/webflow/types/user_access_groups_item_type.py b/src/webflow/types/user_access_groups_item_type.py deleted file mode 100644 index 8d9c81c..0000000 --- a/src/webflow/types/user_access_groups_item_type.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -UserAccessGroupsItemType = typing.Union[typing.Literal["admin", "ecommerce"], typing.Any] diff --git a/src/webflow/types/user_data_data.py b/src/webflow/types/user_data_data.py deleted file mode 100644 index 7bbf36b..0000000 --- a/src/webflow/types/user_data_data.py +++ /dev/null @@ -1,50 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ..core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic -import typing_extensions -from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 - - -class UserDataData(UniversalBaseModel): - name: typing.Optional[str] = pydantic.Field(default=None) - """ - The name of the user - """ - - email: typing.Optional[str] = pydantic.Field(default=None) - """ - The email address of the user - """ - - accept_privacy: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="accept-privacy")] = ( - pydantic.Field(default=None) - ) - """ - Boolean indicating if the user has accepted the privacy policy - """ - - accept_communications: typing_extensions.Annotated[ - typing.Optional[bool], FieldMetadata(alias="accept-communications") - ] = pydantic.Field(default=None) - """ - Boolean indicating if the user has accepted to receive communications - """ - - additional_properties: typing_extensions.Annotated[ - typing.Optional[str], FieldMetadata(alias="additionalProperties") - ] = pydantic.Field(default=None) - """ - Custom user attributes - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_list.py b/src/webflow/types/user_list.py deleted file mode 100644 index b482d69..0000000 --- a/src/webflow/types/user_list.py +++ /dev/null @@ -1,47 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from ..core.pydantic_utilities import UniversalBaseModel -import typing -import pydantic -from .user import User -from ..core.pydantic_utilities import IS_PYDANTIC_V2 - - -class UserList(UniversalBaseModel): - """ - The list users results - """ - - count: typing.Optional[float] = pydantic.Field(default=None) - """ - Number of users returned - """ - - limit: typing.Optional[float] = pydantic.Field(default=None) - """ - The limit specified in the request - """ - - offset: typing.Optional[float] = pydantic.Field(default=None) - """ - The offset specified for pagination - """ - - total: typing.Optional[float] = pydantic.Field(default=None) - """ - Total number of users in the collection - """ - - users: typing.Optional[typing.List[User]] = pydantic.Field(default=None) - """ - List of Users for a Site - """ - - if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 - else: - - class Config: - frozen = True - smart_union = True - extra = pydantic.Extra.allow diff --git a/src/webflow/types/user_status.py b/src/webflow/types/user_status.py deleted file mode 100644 index 9a0147b..0000000 --- a/src/webflow/types/user_status.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing - -UserStatus = typing.Union[typing.Literal["invited", "verified", "unverified"], typing.Any] diff --git a/src/webflow/types/webhook_list.py b/src/webflow/types/webhook_list.py index ea705c4..1740272 100644 --- a/src/webflow/types/webhook_list.py +++ b/src/webflow/types/webhook_list.py @@ -2,15 +2,15 @@ from ..core.pydantic_utilities import UniversalBaseModel import typing -from .pagination import Pagination from .webhook import Webhook +from .pagination import Pagination from ..core.pydantic_utilities import IS_PYDANTIC_V2 import pydantic class WebhookList(UniversalBaseModel): - pagination: typing.Optional[Pagination] = None webhooks: typing.Optional[typing.List[Webhook]] = None + pagination: typing.Optional[Pagination] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/workspace_audit_log_item.py b/src/webflow/types/workspace_audit_log_item.py new file mode 100644 index 0000000..1936c93 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item.py @@ -0,0 +1,162 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations +from ..core.pydantic_utilities import UniversalBaseModel +import typing +import datetime as dt +from .workspace_audit_log_item_actor import WorkspaceAuditLogItemActor +from .workspace_audit_log_item_workspace import WorkspaceAuditLogItemWorkspace +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic +import typing_extensions +from ..core.serialization import FieldMetadata +from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType +from .user_access import UserAccess +from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType +from .custom_role import CustomRole +from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType +from .workspace_membership import WorkspaceMembership +from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType +from .site_membership import SiteMembership +from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType +from .workspace_invitation import WorkspaceInvitation +from .setting_change import SettingChange + + +class Base(UniversalBaseModel): + timestamp: typing.Optional[dt.datetime] = None + actor: typing.Optional[WorkspaceAuditLogItemActor] = None + workspace: typing.Optional[WorkspaceAuditLogItemWorkspace] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class WorkspaceAuditLogItem_UserAccess(Base): + event_type: typing_extensions.Annotated[typing.Literal["user_access"], FieldMetadata(alias="eventType")] = ( + "user_access" + ) + event_sub_type: typing_extensions.Annotated[ + typing.Optional[UserAccessAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[UserAccess] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class WorkspaceAuditLogItem_CustomRole(Base): + event_type: typing_extensions.Annotated[typing.Literal["custom_role"], FieldMetadata(alias="eventType")] = ( + "custom_role" + ) + event_sub_type: typing_extensions.Annotated[ + typing.Optional[CustomRoleAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[CustomRole] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class WorkspaceAuditLogItem_WorkspaceMembership(Base): + event_type: typing_extensions.Annotated[ + typing.Literal["workspace_membership"], FieldMetadata(alias="eventType") + ] = "workspace_membership" + event_sub_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[WorkspaceMembership] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class WorkspaceAuditLogItem_SiteMembership(Base): + event_type: typing_extensions.Annotated[typing.Literal["site_membership"], FieldMetadata(alias="eventType")] = ( + "site_membership" + ) + event_sub_type: typing_extensions.Annotated[ + typing.Optional[SiteMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[SiteMembership] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class WorkspaceAuditLogItem_WorkspaceInvitation(Base): + event_type: typing_extensions.Annotated[ + typing.Literal["workspace_invitation"], FieldMetadata(alias="eventType") + ] = "workspace_invitation" + event_sub_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceInvitationAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[WorkspaceInvitation] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class WorkspaceAuditLogItem_WorkspaceSetting(Base): + event_type: typing_extensions.Annotated[typing.Literal["workspace_setting"], FieldMetadata(alias="eventType")] = ( + "workspace_setting" + ) + event_sub_type: typing_extensions.Annotated[ + typing.Optional[typing.Literal["setting_updated"]], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[SettingChange] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +WorkspaceAuditLogItem = typing.Union[ + WorkspaceAuditLogItem_UserAccess, + WorkspaceAuditLogItem_CustomRole, + WorkspaceAuditLogItem_WorkspaceMembership, + WorkspaceAuditLogItem_SiteMembership, + WorkspaceAuditLogItem_WorkspaceInvitation, + WorkspaceAuditLogItem_WorkspaceSetting, +] diff --git a/src/webflow/types/workspace_audit_log_item_actor.py b/src/webflow/types/workspace_audit_log_item_actor.py new file mode 100644 index 0000000..7da609c --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_actor.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemActor(UniversalBaseModel): + id: typing.Optional[str] = None + email: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_setting_change_method.py b/src/webflow/types/workspace_audit_log_item_payload_setting_change_method.py new file mode 100644 index 0000000..4b91759 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_setting_change_method.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadSettingChangeMethod = typing.Union[typing.Literal["dashboard", "admin"], typing.Any] diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_granular_access.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_granular_access.py new file mode 100644 index 0000000..8d18539 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_granular_access.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess(UniversalBaseModel): + id: typing.Optional[str] = None + name: typing.Optional[str] = None + type: typing.Optional[typing.Literal["cms"]] = None + restricted: typing.Optional[bool] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_method.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_method.py new file mode 100644 index 0000000..a13fbae --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_method.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadSiteMembershipMethod = typing.Union[ + typing.Literal["sso", "invite", "scim", "dashboard", "admin", "access_request"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py new file mode 100644 index 0000000..6d392bd --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemPayloadSiteMembershipSite(UniversalBaseModel): + id: typing.Optional[str] = None + slug: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py new file mode 100644 index 0000000..bcfc37b --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemPayloadSiteMembershipTargetUser(UniversalBaseModel): + id: typing.Optional[str] = None + email: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_user_type.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_user_type.py new file mode 100644 index 0000000..47b5168 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_user_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadSiteMembershipUserType = typing.Union[ + typing.Literal["member", "guest", "reviewer", "client"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_user_access_method.py b/src/webflow/types/workspace_audit_log_item_payload_user_access_method.py new file mode 100644 index 0000000..5417cff --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_user_access_method.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadUserAccessMethod = typing.Union[ + typing.Literal["dashboard", "sso", "api", "google"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_method.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_method.py new file mode 100644 index 0000000..79a3042 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_method.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod = typing.Union[ + typing.Literal["sso", "dashboard", "admin"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py new file mode 100644 index 0000000..1360978 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser(UniversalBaseModel): + id: typing.Optional[str] = None + email: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_users_item.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_users_item.py new file mode 100644 index 0000000..1338b5f --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_users_item.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem(UniversalBaseModel): + id: typing.Optional[str] = None + email: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_user_type.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_user_type.py new file mode 100644 index 0000000..980d3a9 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_user_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType = typing.Union[ + typing.Literal["member", "guest", "reviewer", "client"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_method.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_method.py new file mode 100644 index 0000000..df8982f --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_method.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod = typing.Union[ + typing.Literal["sso", "dashboard", "admin", "access_request"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py new file mode 100644 index 0000000..6ce0f6a --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser(UniversalBaseModel): + id: typing.Optional[str] = None + email: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_user_type.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_user_type.py new file mode 100644 index 0000000..dad636f --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_user_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType = typing.Union[ + typing.Literal["member", "guest", "reviewer", "client"], typing.Any +] diff --git a/src/webflow/types/workspace_audit_log_item_workspace.py b/src/webflow/types/workspace_audit_log_item_workspace.py new file mode 100644 index 0000000..6c13bf5 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_item_workspace.py @@ -0,0 +1,20 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogItemWorkspace(UniversalBaseModel): + id: typing.Optional[str] = None + slug: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_audit_log_response.py b/src/webflow/types/workspace_audit_log_response.py new file mode 100644 index 0000000..f6d0d13 --- /dev/null +++ b/src/webflow/types/workspace_audit_log_response.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing +from .workspace_audit_log_item import WorkspaceAuditLogItem +from .pagination import Pagination +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceAuditLogResponse(UniversalBaseModel): + items: typing.Optional[typing.List[WorkspaceAuditLogItem]] = None + pagination: typing.Optional[Pagination] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_invitation.py b/src/webflow/types/workspace_invitation.py new file mode 100644 index 0000000..a096af1 --- /dev/null +++ b/src/webflow/types/workspace_invitation.py @@ -0,0 +1,57 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .workspace_audit_log_item_payload_workspace_invitation_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, +) +from ..core.serialization import FieldMetadata +from .workspace_audit_log_item_payload_workspace_invitation_method import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod, +) +from .workspace_audit_log_item_payload_workspace_invitation_user_type import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, +) +import pydantic +from .workspace_audit_log_item_payload_workspace_invitation_target_users_item import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem, +) +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class WorkspaceInvitation(UniversalBaseModel): + target_user: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser], FieldMetadata(alias="targetUser") + ] = None + method: typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod] = None + user_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType], FieldMetadata(alias="userType") + ] = None + role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( + default=None + ) + """ + The name of the role that was assigned to the user + """ + + previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( + pydantic.Field(default=None) + ) + """ + The previous role that the user had + """ + + target_users: typing_extensions.Annotated[ + typing.Optional[typing.List[WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem]], + FieldMetadata(alias="targetUsers"), + ] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_invitation_audit_log_item.py b/src/webflow/types/workspace_invitation_audit_log_item.py new file mode 100644 index 0000000..e41f504 --- /dev/null +++ b/src/webflow/types/workspace_invitation_audit_log_item.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType +from ..core.serialization import FieldMetadata +from .workspace_invitation import WorkspaceInvitation +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceInvitationAuditLogItem(UniversalBaseModel): + event_sub_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceInvitationAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[WorkspaceInvitation] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_invitation_audit_log_item_event_sub_type.py b/src/webflow/types/workspace_invitation_audit_log_item_event_sub_type.py new file mode 100644 index 0000000..07ccddb --- /dev/null +++ b/src/webflow/types/workspace_invitation_audit_log_item_event_sub_type.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceInvitationAuditLogItemEventSubType = typing.Union[ + typing.Literal[ + "invite_sent", + "invite_accepted", + "invite_updated", + "invite_canceled", + "invite_declined", + "access_request_accepted", + ], + typing.Any, +] diff --git a/src/webflow/types/workspace_membership.py b/src/webflow/types/workspace_membership.py new file mode 100644 index 0000000..1c369a2 --- /dev/null +++ b/src/webflow/types/workspace_membership.py @@ -0,0 +1,49 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .workspace_audit_log_item_payload_workspace_membership_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, +) +from ..core.serialization import FieldMetadata +from .workspace_audit_log_item_payload_workspace_membership_method import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod, +) +from .workspace_audit_log_item_payload_workspace_membership_user_type import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType, +) +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class WorkspaceMembership(UniversalBaseModel): + target_user: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser], FieldMetadata(alias="targetUser") + ] = None + method: typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod] = None + user_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType], FieldMetadata(alias="userType") + ] = None + role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( + default=None + ) + """ + The name of the role that was assigned to the user + """ + + previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( + pydantic.Field(default=None) + ) + """ + The previous role that the user had + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_membership_audit_log_item.py b/src/webflow/types/workspace_membership_audit_log_item.py new file mode 100644 index 0000000..4ac92d7 --- /dev/null +++ b/src/webflow/types/workspace_membership_audit_log_item.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.pydantic_utilities import UniversalBaseModel +import typing_extensions +import typing +from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType +from ..core.serialization import FieldMetadata +from .workspace_membership import WorkspaceMembership +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class WorkspaceMembershipAuditLogItem(UniversalBaseModel): + event_sub_type: typing_extensions.Annotated[ + typing.Optional[WorkspaceMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + ] = None + payload: typing.Optional[WorkspaceMembership] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/webflow/types/workspace_membership_audit_log_item_event_sub_type.py b/src/webflow/types/workspace_membership_audit_log_item_event_sub_type.py new file mode 100644 index 0000000..4d90d7a --- /dev/null +++ b/src/webflow/types/workspace_membership_audit_log_item_event_sub_type.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +WorkspaceMembershipAuditLogItemEventSubType = typing.Union[ + typing.Literal["user_added", "user_removed", "user_role_updated"], typing.Any +] diff --git a/tests/collections/test_fields.py b/tests/collections/test_fields.py index f64c447..dc18ff3 100644 --- a/tests/collections/test_fields.py +++ b/tests/collections/test_fields.py @@ -3,43 +3,50 @@ from webflow import Webflow from webflow import AsyncWebflow import typing +from webflow import StaticField from ..utilities import validate_response async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "75821f618da60c18383330bcc0ca488b", - "isRequired": False, + "id": "562ac0395358780a1f5e6fbc", "isEditable": True, + "isRequired": False, "type": "RichText", - "slug": "post-body", "displayName": "Post Body", "helpText": "Add the body of your post here", } expected_types: typing.Any = { "id": None, - "isRequired": None, "isEditable": None, + "isRequired": None, "type": None, - "slug": None, "displayName": None, "helpText": None, } response = client.collections.fields.create( collection_id="580e63fc8c9a982ac9b8b745", - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", + request=StaticField( + id="562ac0395358780a1f5e6fbc", + is_editable=True, + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", + ), ) validate_response(response, expected_response, expected_types) async_response = await async_client.collections.fields.create( collection_id="580e63fc8c9a982ac9b8b745", - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", + request=StaticField( + id="562ac0395358780a1f5e6fbc", + is_editable=True, + is_required=False, + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", + ), ) validate_response(async_response, expected_response, expected_types) @@ -68,6 +75,7 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "slug": "post-body", "displayName": "Post Body", "helpText": "Add the body of your post here", + "validations": {"additionalProperties": "additionalProperties"}, } expected_types: typing.Any = { "id": None, @@ -77,6 +85,7 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "slug": None, "displayName": None, "helpText": None, + "validations": {"additionalProperties": None}, } response = client.collections.fields.update( collection_id="580e63fc8c9a982ac9b8b745", diff --git a/tests/collections/test_items.py b/tests/collections/test_items.py index fc926a7..0b0807c 100644 --- a/tests/collections/test_items.py +++ b/tests/collections/test_items.py @@ -6,12 +6,15 @@ from ..utilities import validate_response from webflow import CollectionItemPostSingle from webflow import CollectionItemPostSingleFieldData +from webflow.resources.collections.resources.items import ItemsDeleteItemsRequestItemsItem from webflow import CollectionItemWithIdInput from webflow import CollectionItemWithIdInputFieldData from webflow import CollectionItem from webflow import CollectionItemFieldData +from webflow.resources.collections.resources.items import ItemsDeleteItemsLiveRequestItemsItem from webflow.resources.collections.resources.items import SingleCmsItem from webflow import CollectionItemPatchSingleFieldData +from webflow.resources.collections.resources.items import ItemIDs async def test_list_items(client: Webflow, async_client: AsyncWebflow) -> None: @@ -76,12 +79,30 @@ async def test_list_items(client: Webflow, async_client: AsyncWebflow) -> None: }, }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } - response = client.collections.items.list_items(collection_id="580e63fc8c9a982ac9b8b745") + response = client.collections.items.list_items( + collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_id="cmsLocaleId", + offset=1, + limit=1, + name="name", + slug="slug", + sort_by="lastPublished", + sort_order="asc", + ) validate_response(response, expected_response, expected_types) - async_response = await async_client.collections.items.list_items(collection_id="580e63fc8c9a982ac9b8b745") + async_response = await async_client.collections.items.list_items( + collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_id="cmsLocaleId", + offset=1, + limit=1, + name="name", + slug="slug", + sort_by="lastPublished", + sort_order="asc", + ) validate_response(async_response, expected_response, expected_types) @@ -95,11 +116,30 @@ async def test_create_item(client: Webflow, async_client: AsyncWebflow) -> None: "isArchived": False, "isDraft": False, "fieldData": { - "name": "Pan Galactic Gargle Blaster Recipe", - "slug": "pan-galactic-gargle-blaster", - "color": "#db4b68", - "date": "2022-11-18T00:00:00.000Z", - "featured": True, + "name": "The Hitchhiker's Guide to the Galaxy", + "slug": "hitchhikers-guide-to-the-galaxy", + "plain-text": "Don't Panic.", + "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", + "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + "image-gallery": [ + {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, + {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + ], + "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", + "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", + "contact-email": "zaphod.beeblebrox@heartofgold.gov", + "support-phone": "424-242-4242", + "answer-to-everything": 42, + "release-date": "1979-10-12T00:00:00.000Z", + "is-featured": True, + "brand-color": "#000000", + "category": "62b720ef280c7a7a3be8cabf", + "author": "62b720ef280c7a7a3be8cab0", + "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], + "downloadable-asset": { + "fileId": "62b720ef280c7a7a3be8cab3", + "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", + }, }, } expected_types: typing.Any = { @@ -114,11 +154,12 @@ async def test_create_item(client: Webflow, async_client: AsyncWebflow) -> None: } response = client.collections.items.create_item( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, request=CollectionItemPostSingle( is_archived=False, is_draft=False, field_data=CollectionItemPostSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" ), ), ) @@ -126,11 +167,12 @@ async def test_create_item(client: Webflow, async_client: AsyncWebflow) -> None: async_response = await async_client.collections.items.create_item( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, request=CollectionItemPostSingle( is_archived=False, is_draft=False, field_data=CollectionItemPostSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" ), ), ) @@ -140,45 +182,127 @@ async def test_create_item(client: Webflow, async_client: AsyncWebflow) -> None: async def test_delete_items(client: Webflow, async_client: AsyncWebflow) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value assert ( - client.collections.items.delete_items(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + client.collections.items.delete_items( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ItemsDeleteItemsRequestItemsItem(id="580e64008c9a982ac9b8b754")], + ) # type: ignore[func-returns-value] is None ) assert ( - await async_client.collections.items.delete_items(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + await async_client.collections.items.delete_items( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ItemsDeleteItemsRequestItemsItem(id="580e64008c9a982ac9b8b754")], + ) # type: ignore[func-returns-value] is None ) async def test_update_items(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "id", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2023-03-17T18:47:35.560Z", - "lastUpdated": "2023-03-17T18:47:35.560Z", - "createdOn": "2023-03-17T18:47:35.560Z", - "isArchived": True, - "isDraft": True, - "fieldData": { - "name": "My new item", - "slug": "my-new-item", - "date": "2022-11-18T00:00:00.000Z", - "featured": False, - "color": "#db4b68", - }, + "items": [ + { + "id": "66f6ed9576ddacf3149d5ea6", + "cmsLocaleId": "66f6e966c9e1dc700a857ca5", + "lastPublished": "2024-09-27T17:38:29.066Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": False, + "isDraft": False, + "fieldData": {"name": "Ne Paniquez Pas", "slug": "ne-paniquez-pas", "featured": False}, + }, + { + "id": "66f6ed9576ddacf3149d5ea6", + "cmsLocaleId": "66f6e966c9e1dc700a857ca4", + "lastPublished": "2024-09-27T17:38:29.066Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": False, + "isDraft": False, + "fieldData": {"name": "No Entrar en Pánico", "slug": "no-entrar-en-panico", "featured": False}, + }, + { + "id": "66f6ed9576ddacf3149d5eaa", + "cmsLocaleId": "66f6e966c9e1dc700a857ca5", + "lastPublished": "2024-09-27T17:38:29.066Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Au Revoir et Merci pour Tous les Poissons", + "slug": "au-revoir-et-merci", + "featured": False, + }, + }, + { + "id": "66f6ed9576ddacf3149d5eaa", + "cmsLocaleId": "66f6e966c9e1dc700a857ca4", + "lastPublished": "2024-09-27T17:38:29.066Z", + "lastUpdated": "2024-09-27T17:38:29.066Z", + "createdOn": "2024-09-27T17:38:29.066Z", + "isArchived": False, + "isDraft": False, + "fieldData": { + "name": "Hasta Luego y Gracias por Todo el Pescado", + "slug": "hasta-luego-y-gracias", + "featured": False, + }, + }, + ], + "pagination": {"limit": 25, "offset": 0, "total": 4}, } expected_types: typing.Any = { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, + "items": ( + "list", + { + 0: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + 1: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + 2: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + 3: { + "id": None, + "cmsLocaleId": None, + "lastPublished": None, + "lastUpdated": None, + "createdOn": None, + "isArchived": None, + "isDraft": None, + "fieldData": {"name": None, "slug": None}, + }, + }, + ), + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } response = client.collections.items.update_items( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, items=[ CollectionItemWithIdInput( id="66f6ed9576ddacf3149d5ea6", @@ -210,6 +334,7 @@ async def test_update_items(client: Webflow, async_client: AsyncWebflow) -> None async_response = await async_client.collections.items.update_items( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, items=[ CollectionItemWithIdInput( id="66f6ed9576ddacf3149d5ea6", @@ -302,12 +427,30 @@ async def test_list_items_live(client: Webflow, async_client: AsyncWebflow) -> N }, }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } - response = client.collections.items.list_items_live(collection_id="580e63fc8c9a982ac9b8b745") + response = client.collections.items.list_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_id="cmsLocaleId", + offset=1, + limit=1, + name="name", + slug="slug", + sort_by="lastPublished", + sort_order="asc", + ) validate_response(response, expected_response, expected_types) - async_response = await async_client.collections.items.list_items_live(collection_id="580e63fc8c9a982ac9b8b745") + async_response = await async_client.collections.items.list_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + cms_locale_id="cmsLocaleId", + offset=1, + limit=1, + name="name", + slug="slug", + sort_by="lastPublished", + sort_order="asc", + ) validate_response(async_response, expected_response, expected_types) @@ -321,11 +464,30 @@ async def test_create_item_live(client: Webflow, async_client: AsyncWebflow) -> "isArchived": False, "isDraft": False, "fieldData": { - "name": "Pan Galactic Gargle Blaster Recipe", - "slug": "pan-galactic-gargle-blaster", - "color": "#db4b68", - "date": "2022-11-18T00:00:00.000Z", - "featured": True, + "name": "The Hitchhiker's Guide to the Galaxy", + "slug": "hitchhikers-guide-to-the-galaxy", + "plain-text": "Don't Panic.", + "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", + "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + "image-gallery": [ + {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, + {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + ], + "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", + "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", + "contact-email": "zaphod.beeblebrox@heartofgold.gov", + "support-phone": "424-242-4242", + "answer-to-everything": 42, + "release-date": "1979-10-12T00:00:00.000Z", + "is-featured": True, + "brand-color": "#000000", + "category": "62b720ef280c7a7a3be8cabf", + "author": "62b720ef280c7a7a3be8cab0", + "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], + "downloadable-asset": { + "fileId": "62b720ef280c7a7a3be8cab3", + "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", + }, }, } expected_types: typing.Any = { @@ -340,11 +502,12 @@ async def test_create_item_live(client: Webflow, async_client: AsyncWebflow) -> } response = client.collections.items.create_item_live( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, request=CollectionItem( is_archived=False, is_draft=False, field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" ), ), ) @@ -352,11 +515,12 @@ async def test_create_item_live(client: Webflow, async_client: AsyncWebflow) -> async_response = await async_client.collections.items.create_item_live( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, request=CollectionItem( is_archived=False, is_draft=False, field_data=CollectionItemFieldData( - name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" ), ), ) @@ -366,12 +530,18 @@ async def test_create_item_live(client: Webflow, async_client: AsyncWebflow) -> async def test_delete_items_live(client: Webflow, async_client: AsyncWebflow) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value assert ( - client.collections.items.delete_items_live(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + client.collections.items.delete_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ItemsDeleteItemsLiveRequestItemsItem(id="580e64008c9a982ac9b8b754")], + ) # type: ignore[func-returns-value] is None ) assert ( - await async_client.collections.items.delete_items_live(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] + await async_client.collections.items.delete_items_live( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ItemsDeleteItemsLiveRequestItemsItem(id="580e64008c9a982ac9b8b754")], + ) # type: ignore[func-returns-value] is None ) @@ -382,31 +552,31 @@ async def test_update_items_live(client: Webflow, async_client: AsyncWebflow) -> { "id": "66f6ed9576ddacf3149d5ea6", "cmsLocaleId": "66f6e966c9e1dc700a857ca5", - "lastPublished": "2023-03-17T18:47:35.560Z", + "lastPublished": "2024-09-27T17:38:29.066Z", "lastUpdated": "2024-09-27T17:38:29.066Z", "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": True, - "isDraft": True, + "isArchived": False, + "isDraft": False, "fieldData": {"name": "Ne Paniquez Pas", "slug": "ne-paniquez-pas", "featured": False}, }, { "id": "66f6ed9576ddacf3149d5ea6", "cmsLocaleId": "66f6e966c9e1dc700a857ca4", - "lastPublished": "2023-03-17T18:47:35.560Z", + "lastPublished": "2024-09-27T17:38:29.066Z", "lastUpdated": "2024-09-27T17:38:29.066Z", "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": True, - "isDraft": True, + "isArchived": False, + "isDraft": False, "fieldData": {"name": "No Entrar en Pánico", "slug": "no-entrar-en-panico", "featured": False}, }, { "id": "66f6ed9576ddacf3149d5eaa", "cmsLocaleId": "66f6e966c9e1dc700a857ca5", - "lastPublished": "2023-03-17T18:47:35.560Z", + "lastPublished": "2024-09-27T17:38:29.066Z", "lastUpdated": "2024-09-27T17:38:29.066Z", "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": True, - "isDraft": True, + "isArchived": False, + "isDraft": False, "fieldData": { "name": "Au Revoir et Merci pour Tous les Poissons", "slug": "au-revoir-et-merci", @@ -416,11 +586,11 @@ async def test_update_items_live(client: Webflow, async_client: AsyncWebflow) -> { "id": "66f6ed9576ddacf3149d5eaa", "cmsLocaleId": "66f6e966c9e1dc700a857ca4", - "lastPublished": "2023-03-17T18:47:35.560Z", + "lastPublished": "2024-09-27T17:38:29.066Z", "lastUpdated": "2024-09-27T17:38:29.066Z", "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": True, - "isDraft": True, + "isArchived": False, + "isDraft": False, "fieldData": { "name": "Hasta Luego y Gracias por Todo el Pescado", "slug": "hasta-luego-y-gracias", @@ -478,6 +648,7 @@ async def test_update_items_live(client: Webflow, async_client: AsyncWebflow) -> } response = client.collections.items.update_items_live( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, items=[ CollectionItemWithIdInput( id="66f6ed9576ddacf3149d5ea6", @@ -509,6 +680,7 @@ async def test_update_items_live(client: Webflow, async_client: AsyncWebflow) -> async_response = await async_client.collections.items.update_items_live( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, items=[ CollectionItemWithIdInput( id="66f6ed9576ddacf3149d5ea6", @@ -568,6 +740,7 @@ async def test_create_items(client: Webflow, async_client: AsyncWebflow) -> None } response = client.collections.items.create_items( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, cms_locale_ids=["66f6e966c9e1dc700a857ca3", "66f6e966c9e1dc700a857ca4", "66f6e966c9e1dc700a857ca5"], is_archived=False, is_draft=False, @@ -577,6 +750,7 @@ async def test_create_items(client: Webflow, async_client: AsyncWebflow) -> None async_response = await async_client.collections.items.create_items( collection_id="580e63fc8c9a982ac9b8b745", + skip_invalid_files=True, cms_locale_ids=["66f6e966c9e1dc700a857ca3", "66f6e966c9e1dc700a857ca4", "66f6e966c9e1dc700a857ca5"], is_archived=False, is_draft=False, @@ -595,11 +769,30 @@ async def test_get_item(client: Webflow, async_client: AsyncWebflow) -> None: "isArchived": False, "isDraft": False, "fieldData": { - "name": "Pan Galactic Gargle Blaster Recipe", - "slug": "pan-galactic-gargle-blaster", - "color": "#db4b68", - "date": "2022-11-18T00:00:00.000Z", - "featured": True, + "name": "The Hitchhiker's Guide to the Galaxy", + "slug": "hitchhikers-guide-to-the-galaxy", + "plain-text": "Don't Panic.", + "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", + "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + "image-gallery": [ + {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, + {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + ], + "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", + "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", + "contact-email": "zaphod.beeblebrox@heartofgold.gov", + "support-phone": "424-242-4242", + "answer-to-everything": 42, + "release-date": "1979-10-12T00:00:00.000Z", + "is-featured": True, + "brand-color": "#000000", + "category": "62b720ef280c7a7a3be8cabf", + "author": "62b720ef280c7a7a3be8cab0", + "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], + "downloadable-asset": { + "fileId": "62b720ef280c7a7a3be8cab3", + "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", + }, }, } expected_types: typing.Any = { @@ -613,12 +806,12 @@ async def test_get_item(client: Webflow, async_client: AsyncWebflow) -> None: "fieldData": {"name": None, "slug": None}, } response = client.collections.items.get_item( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" ) validate_response(response, expected_response, expected_types) async_response = await async_client.collections.items.get_item( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" ) validate_response(async_response, expected_response, expected_types) @@ -627,14 +820,14 @@ async def test_delete_item(client: Webflow, async_client: AsyncWebflow) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value assert ( client.collections.items.delete_item( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" ) # type: ignore[func-returns-value] is None ) assert ( await async_client.collections.items.delete_item( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" ) # type: ignore[func-returns-value] is None ) @@ -650,11 +843,30 @@ async def test_update_item(client: Webflow, async_client: AsyncWebflow) -> None: "isArchived": False, "isDraft": False, "fieldData": { - "name": "Pan Galactic Gargle Blaster Recipe", - "slug": "pan-galactic-gargle-blaster", - "color": "#db4b68", - "date": "2022-11-18T00:00:00.000Z", - "featured": True, + "name": "The Hitchhiker's Guide to the Galaxy", + "slug": "hitchhikers-guide-to-the-galaxy", + "plain-text": "Don't Panic.", + "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", + "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + "image-gallery": [ + {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, + {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + ], + "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", + "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", + "contact-email": "zaphod.beeblebrox@heartofgold.gov", + "support-phone": "424-242-4242", + "answer-to-everything": 42, + "release-date": "1979-10-12T00:00:00.000Z", + "is-featured": True, + "brand-color": "#000000", + "category": "62b720ef280c7a7a3be8cabf", + "author": "62b720ef280c7a7a3be8cab0", + "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], + "downloadable-asset": { + "fileId": "62b720ef280c7a7a3be8cab3", + "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", + }, }, } expected_types: typing.Any = { @@ -670,10 +882,11 @@ async def test_update_item(client: Webflow, async_client: AsyncWebflow) -> None: response = client.collections.items.update_item( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + skip_invalid_files=True, is_archived=False, is_draft=False, field_data=CollectionItemPatchSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" ), ) validate_response(response, expected_response, expected_types) @@ -681,10 +894,11 @@ async def test_update_item(client: Webflow, async_client: AsyncWebflow) -> None: async_response = await async_client.collections.items.update_item( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + skip_invalid_files=True, is_archived=False, is_draft=False, field_data=CollectionItemPatchSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" ), ) validate_response(async_response, expected_response, expected_types) @@ -700,11 +914,30 @@ async def test_get_item_live(client: Webflow, async_client: AsyncWebflow) -> Non "isArchived": False, "isDraft": False, "fieldData": { - "name": "Pan Galactic Gargle Blaster Recipe", - "slug": "pan-galactic-gargle-blaster", - "color": "#db4b68", - "date": "2022-11-18T00:00:00.000Z", - "featured": True, + "name": "The Hitchhiker's Guide to the Galaxy", + "slug": "hitchhikers-guide-to-the-galaxy", + "plain-text": "Don't Panic.", + "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", + "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + "image-gallery": [ + {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, + {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + ], + "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", + "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", + "contact-email": "zaphod.beeblebrox@heartofgold.gov", + "support-phone": "424-242-4242", + "answer-to-everything": 42, + "release-date": "1979-10-12T00:00:00.000Z", + "is-featured": True, + "brand-color": "#000000", + "category": "62b720ef280c7a7a3be8cabf", + "author": "62b720ef280c7a7a3be8cab0", + "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], + "downloadable-asset": { + "fileId": "62b720ef280c7a7a3be8cab3", + "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", + }, }, } expected_types: typing.Any = { @@ -718,12 +951,12 @@ async def test_get_item_live(client: Webflow, async_client: AsyncWebflow) -> Non "fieldData": {"name": None, "slug": None}, } response = client.collections.items.get_item_live( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" ) validate_response(response, expected_response, expected_types) async_response = await async_client.collections.items.get_item_live( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" ) validate_response(async_response, expected_response, expected_types) @@ -732,14 +965,14 @@ async def test_delete_item_live(client: Webflow, async_client: AsyncWebflow) -> # Type ignore to avoid mypy complaining about the function not being meant to return a value assert ( client.collections.items.delete_item_live( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" ) # type: ignore[func-returns-value] is None ) assert ( await async_client.collections.items.delete_item_live( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" ) # type: ignore[func-returns-value] is None ) @@ -755,11 +988,30 @@ async def test_update_item_live(client: Webflow, async_client: AsyncWebflow) -> "isArchived": False, "isDraft": False, "fieldData": { - "name": "Pan Galactic Gargle Blaster Recipe", - "slug": "pan-galactic-gargle-blaster", - "color": "#db4b68", - "date": "2022-11-18T00:00:00.000Z", - "featured": True, + "name": "The Hitchhiker's Guide to the Galaxy", + "slug": "hitchhikers-guide-to-the-galaxy", + "plain-text": "Don't Panic.", + "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", + "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + "image-gallery": [ + {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, + {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, + ], + "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", + "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", + "contact-email": "zaphod.beeblebrox@heartofgold.gov", + "support-phone": "424-242-4242", + "answer-to-everything": 42, + "release-date": "1979-10-12T00:00:00.000Z", + "is-featured": True, + "brand-color": "#000000", + "category": "62b720ef280c7a7a3be8cabf", + "author": "62b720ef280c7a7a3be8cab0", + "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], + "downloadable-asset": { + "fileId": "62b720ef280c7a7a3be8cab3", + "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", + }, }, } expected_types: typing.Any = { @@ -775,10 +1027,11 @@ async def test_update_item_live(client: Webflow, async_client: AsyncWebflow) -> response = client.collections.items.update_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + skip_invalid_files=True, is_archived=False, is_draft=False, field_data=CollectionItemPatchSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" ), ) validate_response(response, expected_response, expected_types) @@ -786,10 +1039,11 @@ async def test_update_item_live(client: Webflow, async_client: AsyncWebflow) -> async_response = await async_client.collections.items.update_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", + skip_invalid_files=True, is_archived=False, is_draft=False, field_data=CollectionItemPatchSingleFieldData( - name="Pan Galactic Gargle Blaster Recipe", slug="pan-galactic-gargle-blaster" + name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" ), ) validate_response(async_response, expected_response, expected_types) @@ -801,10 +1055,14 @@ async def test_publish_item(client: Webflow, async_client: AsyncWebflow) -> None "errors": ["Staging item ID 643fd856d66b6528195ee2cf not found."], } expected_types: typing.Any = {"publishedItemIds": ("list", {0: None, 1: None}), "errors": ("list", {0: None})} - response = client.collections.items.publish_item(collection_id="580e63fc8c9a982ac9b8b745", item_ids=["itemIds"]) + response = client.collections.items.publish_item( + collection_id="580e63fc8c9a982ac9b8b745", + request=ItemIDs(item_ids=["643fd856d66b6528195ee2ca", "643fd856d66b6528195ee2cb", "643fd856d66b6528195ee2cc"]), + ) validate_response(response, expected_response, expected_types) async_response = await async_client.collections.items.publish_item( - collection_id="580e63fc8c9a982ac9b8b745", item_ids=["itemIds"] + collection_id="580e63fc8c9a982ac9b8b745", + request=ItemIDs(item_ids=["643fd856d66b6528195ee2ca", "643fd856d66b6528195ee2cb", "643fd856d66b6528195ee2cc"]), ) validate_response(async_response, expected_response, expected_types) diff --git a/tests/conftest.py b/tests/conftest.py index 019aab8..398d344 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,6 +2,7 @@ from webflow import Webflow import os +from webflow.environment import WebflowEnvironment import pytest from webflow import AsyncWebflow @@ -9,12 +10,22 @@ @pytest.fixture def client() -> Webflow: return Webflow( - access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), base_url=os.getenv("TESTS_BASE_URL", "base_url") + access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), + environment=WebflowEnvironment( + base=os.getenv("TESTS_BASE_URL", "base_url"), + data_api=os.getenv("TESTS_BASE_URL", "base_url"), + content_delivery_api=os.getenv("TESTS_BASE_URL", "base_url"), + ), ) @pytest.fixture def async_client() -> AsyncWebflow: return AsyncWebflow( - access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), base_url=os.getenv("TESTS_BASE_URL", "base_url") + access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), + environment=WebflowEnvironment( + base=os.getenv("TESTS_BASE_URL", "base_url"), + data_api=os.getenv("TESTS_BASE_URL", "base_url"), + content_delivery_api=os.getenv("TESTS_BASE_URL", "base_url"), + ), ) diff --git a/tests/sites/test_activity_logs.py b/tests/sites/test_activity_logs.py index f289464..5046daa 100644 --- a/tests/sites/test_activity_logs.py +++ b/tests/sites/test_activity_logs.py @@ -44,10 +44,10 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: } }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } - response = client.sites.activity_logs.list(site_id="580e63e98c9a982ac9b8b741") + response = client.sites.activity_logs.list(site_id="580e63e98c9a982ac9b8b741", limit=1, offset=1) validate_response(response, expected_response, expected_types) - async_response = await async_client.sites.activity_logs.list(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.sites.activity_logs.list(site_id="580e63e98c9a982ac9b8b741", limit=1, offset=1) validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_comments.py b/tests/sites/test_comments.py new file mode 100644 index 0000000..a8a81b6 --- /dev/null +++ b/tests/sites/test_comments.py @@ -0,0 +1,242 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response + + +async def test_list_comment_threads(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "comments": [ + { + "id": "679d2ddb5196117ad04d1ffa", + "siteId": "679826b3b20b045e176bc4b5", + "pageId": "679826b3b20b045e176bc4bc", + "localeId": "67993753d910db250db64b3e", + "itemId": "580e64008c9a982ac9b8b754", + "breakpoint": "main", + "url": "https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc", + "content": "Let's go to the pub! [[6287ec36a841b25637c663df]] ", + "isResolved": False, + "author": { + "userId": "6287ec36a841b25637c663df", + "email": "ford.prefect@heartofgold.spaceship", + "name": "Ford Prefect", + }, + "mentionedUsers": [ + { + "userId": "6287ec36a841b25637c663df", + "email": "arthur.dent@heartofgold.spaceship", + "name": "Arthur Dent", + } + ], + "createdOn": "2025-01-31T20:08:59.759Z", + "lastUpdated": "2025-01-31T20:08:59.759Z", + }, + { + "id": "679d2ddb5196117ad04d1ffc", + "siteId": "679826b3b20b045e176bc4b5", + "pageId": "679826b3b20b045e176bc4bc", + "localeId": "67993753d910db250db64b3e", + "itemId": "580e64008c9a982ac9b8b754", + "breakpoint": "main", + "url": "https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc", + "content": "You have five minutes left to drink it [[6287ec36a841b25637c663df]] ", + "isResolved": False, + "author": { + "userId": "6287ec36a841b25637c663df", + "email": "ford.prefect@heartofgold.spaceship", + "name": "Ford Prefect", + }, + "mentionedUsers": [ + { + "userId": "6287ec36a841b25637c663df", + "email": "arthur.dent@heartofgold.spaceship", + "name": "Arthur Dent", + } + ], + "createdOn": "2025-01-31T20:08:59.759Z", + "lastUpdated": "2025-01-31T20:08:59.759Z", + }, + ], + "pagination": {"limit": 2, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "comments": ( + "list", + { + 0: { + "id": None, + "siteId": None, + "pageId": None, + "localeId": None, + "itemId": None, + "breakpoint": None, + "url": None, + "content": None, + "isResolved": None, + "author": {"userId": None, "email": None, "name": None}, + "mentionedUsers": ("list", {0: {"userId": None, "email": None, "name": None}}), + "createdOn": None, + "lastUpdated": None, + }, + 1: { + "id": None, + "siteId": None, + "pageId": None, + "localeId": None, + "itemId": None, + "breakpoint": None, + "url": None, + "content": None, + "isResolved": None, + "author": {"userId": None, "email": None, "name": None}, + "mentionedUsers": ("list", {0: {"userId": None, "email": None, "name": None}}), + "createdOn": None, + "lastUpdated": None, + }, + }, + ), + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, + } + response = client.sites.comments.list_comment_threads( + site_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.comments.list_comment_threads( + site_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get_comment_thread(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "580e64008c9a982ac9b8b754", + "siteId": "580e64008c9a982ac9b8b754", + "pageId": "580e64008c9a982ac9b8b754", + "localeId": "580e64008c9a982ac9b8b754", + "itemId": "580e64008c9a982ac9b8b754", + "breakpoint": "main", + "url": "https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc", + "content": "This is a comment reply", + "isResolved": True, + "author": {"userId": "userId", "email": "email", "name": "name"}, + "mentionedUsers": [ + {"userId": "6287ec36a841b25637c663df", "email": "arthur.dent@heartofgold.spaceship", "name": "Arthur Dent"} + ], + "createdOn": "2023-03-17T18:47:35.560Z", + "lastUpdated": "2023-03-17T18:47:35.560Z", + } + expected_types: typing.Any = { + "id": None, + "siteId": None, + "pageId": None, + "localeId": None, + "itemId": None, + "breakpoint": None, + "url": None, + "content": None, + "isResolved": None, + "author": {"userId": None, "email": None, "name": None}, + "mentionedUsers": ("list", {0: {"userId": None, "email": None, "name": None}}), + "createdOn": None, + "lastUpdated": None, + } + response = client.sites.comments.get_comment_thread( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.comments.get_comment_thread( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_list_comment_replies(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "comments": [ + { + "id": "679d2ddb5196117ad04d1ffa", + "commentId": "679d2ddb5196117ad04d1ff8", + "siteId": "679826b3b20b045e176bc4b5", + "pageId": "679826b3b20b045e176bc4bc", + "localeId": "67993753d910db250db64b3e", + "breakpoint": "main", + "content": "This comment mentions another user [[6287ec36a841b25637c663df]] ", + "isResolved": False, + "author": {"id": "id", "email": "email", "name": "name"}, + "mentionedUsers": [{"id": "id", "email": "arthur.dent@example.com", "name": "Arthur Dent"}], + "lastUpdated": "2025-01-31T20:08:59.759Z", + "createdOn": "2025-01-31T20:08:59.759Z", + } + ], + "pagination": {"limit": 2, "offset": 0, "total": 1}, + } + expected_types: typing.Any = { + "comments": ( + "list", + { + 0: { + "id": None, + "commentId": None, + "siteId": None, + "pageId": None, + "localeId": None, + "breakpoint": None, + "content": None, + "isResolved": None, + "author": {"id": None, "email": None, "name": None}, + "mentionedUsers": ("list", {0: {"id": None, "email": None, "name": None}}), + "lastUpdated": None, + "createdOn": None, + } + }, + ), + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, + } + response = client.sites.comments.list_comment_replies( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.comments.list_comment_replies( + site_id="580e63e98c9a982ac9b8b741", + comment_thread_id="580e63e98c9a982ac9b8b741", + locale_id="65427cf400e02b306eaa04a0", + offset=1, + limit=1, + sort_by="createdOn", + sort_order="asc", + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_forms.py b/tests/sites/test_forms.py new file mode 100644 index 0000000..bb8b724 --- /dev/null +++ b/tests/sites/test_forms.py @@ -0,0 +1,193 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response + + +async def test_list_submissions_by_site(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "formSubmissions": [ + { + "id": "6321ca84df3949bfc6752327", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, + }, + { + "id": "660d64fabf6e0a0d4edab981", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Ford", "Last Name": "Prefect"}, + }, + ], + "pagination": {"limit": 25, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "formSubmissions": ( + "list", + { + 0: { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + }, + 1: { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + }, + }, + ), + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, + } + response = client.sites.forms.list_submissions_by_site( + site_id="580e63e98c9a982ac9b8b741", element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0", offset=1, limit=1 + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.forms.list_submissions_by_site( + site_id="580e63e98c9a982ac9b8b741", element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0", offset=1, limit=1 + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_list_submissions(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "formSubmissions": [ + { + "id": "6321ca84df3949bfc6752327", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, + }, + { + "id": "660d64fabf6e0a0d4edab981", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Ford", "Last Name": "Prefect"}, + }, + ], + "pagination": {"limit": 25, "offset": 0, "total": 2}, + } + expected_types: typing.Any = { + "formSubmissions": ( + "list", + { + 0: { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + }, + 1: { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + }, + }, + ), + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, + } + response = client.sites.forms.list_submissions( + site_id="580e63e98c9a982ac9b8b741", form_id="580e63e98c9a982ac9b8b741", offset=1, limit=1 + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.forms.list_submissions( + site_id="580e63e98c9a982ac9b8b741", form_id="580e63e98c9a982ac9b8b741", offset=1, limit=1 + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_get_submission(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "6321ca84df3949bfc6752327", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, + } + expected_types: typing.Any = { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + } + response = client.sites.forms.get_submission( + site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.forms.get_submission( + site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete_submission(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.sites.forms.delete_submission( + site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" + ) # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.sites.forms.delete_submission( + site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" + ) # type: ignore[func-returns-value] + is None + ) + + +async def test_update_submission(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "id": "6321ca84df3949bfc6752327", + "displayName": "Sample Form", + "siteId": "62749158efef318abc8d5a0f", + "workspaceId": "62749158efef318abc8d5a0f", + "dateSubmitted": "2022-09-14T12:35:16Z", + "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, + } + expected_types: typing.Any = { + "id": None, + "displayName": None, + "siteId": None, + "workspaceId": None, + "dateSubmitted": "datetime", + "formResponse": ("dict", {0: (None, None), 1: (None, None)}), + } + response = client.sites.forms.update_submission( + site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.forms.update_submission( + site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_redirects.py b/tests/sites/test_redirects.py index e10b50e..59b7a48 100644 --- a/tests/sites/test_redirects.py +++ b/tests/sites/test_redirects.py @@ -19,7 +19,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "list", {0: {"id": None, "fromUrl": None, "toUrl": None}, 1: {"id": None, "fromUrl": None, "toUrl": None}}, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } response = client.sites.redirects.list(site_id="580e63e98c9a982ac9b8b741") validate_response(response, expected_response, expected_types) @@ -55,7 +55,7 @@ async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: "list", {0: {"id": None, "fromUrl": None, "toUrl": None}, 1: {"id": None, "fromUrl": None, "toUrl": None}}, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } response = client.sites.redirects.delete(site_id="580e63e98c9a982ac9b8b741", redirect_id="66c4cb9a20cac35ed19500e6") validate_response(response, expected_response, expected_types) diff --git a/tests/sites/test_robots_txt.py b/tests/sites/test_robots_txt.py new file mode 100644 index 0000000..cb38204 --- /dev/null +++ b/tests/sites/test_robots_txt.py @@ -0,0 +1,145 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +from ..utilities import validate_response +from webflow import RobotsRulesItem + + +async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "rules": [ + { + "userAgent": "googlebot", + "allows": ["/public"], + "disallows": ["/vogon-poetry", "/total-perspective-vortex"], + } + ], + "sitemap": "https://heartofgold.ship/sitemap.xml", + } + expected_types: typing.Any = { + "rules": ( + "list", + {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, + ), + "sitemap": None, + } + response = client.sites.robots_txt.get(site_id="580e63e98c9a982ac9b8b741") + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.robots_txt.get(site_id="580e63e98c9a982ac9b8b741") + validate_response(async_response, expected_response, expected_types) + + +async def test_put(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "rules": [ + { + "userAgent": "googlebot", + "allows": ["/public"], + "disallows": ["/vogon-poetry", "/total-perspective-vortex"], + } + ], + "sitemap": "https://heartofgold.ship/sitemap.xml", + } + expected_types: typing.Any = { + "rules": ( + "list", + {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, + ), + "sitemap": None, + } + response = client.sites.robots_txt.put( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.robots_txt.put( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "rules": [ + { + "userAgent": "googlebot", + "allows": ["/public"], + "disallows": ["/vogon-poetry", "/total-perspective-vortex"], + } + ], + "sitemap": "https://heartofgold.ship/sitemap.xml", + } + expected_types: typing.Any = { + "rules": ( + "list", + {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, + ), + "sitemap": None, + } + response = client.sites.robots_txt.delete( + site_id="580e63e98c9a982ac9b8b741", + rules=[RobotsRulesItem(user_agent="*", allows=["/public"], disallows=["/bubbles"])], + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.robots_txt.delete( + site_id="580e63e98c9a982ac9b8b741", + rules=[RobotsRulesItem(user_agent="*", allows=["/public"], disallows=["/bubbles"])], + ) + validate_response(async_response, expected_response, expected_types) + + +async def test_patch(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "rules": [ + { + "userAgent": "googlebot", + "allows": ["/public"], + "disallows": ["/vogon-poetry", "/total-perspective-vortex"], + } + ], + "sitemap": "https://heartofgold.ship/sitemap.xml", + } + expected_types: typing.Any = { + "rules": ( + "list", + {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, + ), + "sitemap": None, + } + response = client.sites.robots_txt.patch( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.sites.robots_txt.patch( + site_id="580e63e98c9a982ac9b8b741", + rules=[ + RobotsRulesItem( + user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] + ) + ], + sitemap="https://heartofgold.ship/sitemap.xml", + ) + validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_scripts.py b/tests/sites/test_scripts.py index cc5d71c..47c5179 100644 --- a/tests/sites/test_scripts.py +++ b/tests/sites/test_scripts.py @@ -145,10 +145,12 @@ async def test_list_custom_code_blocks(client: Webflow, async_client: AsyncWebfl }, }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } - response = client.sites.scripts.list_custom_code_blocks(site_id="580e63e98c9a982ac9b8b741") + response = client.sites.scripts.list_custom_code_blocks(site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) validate_response(response, expected_response, expected_types) - async_response = await async_client.sites.scripts.list_custom_code_blocks(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.sites.scripts.list_custom_code_blocks( + site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1 + ) validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_well_known.py b/tests/sites/test_well_known.py new file mode 100644 index 0000000..ad81052 --- /dev/null +++ b/tests/sites/test_well_known.py @@ -0,0 +1,40 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow + + +async def test_put(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.sites.well_known.put( + site_id="580e63e98c9a982ac9b8b741", + file_name="apple-app-site-association.txt", + file_data='{\n "applinks": {\n "apps": [],\n "details": [\n {\n "appID": "ABCDE12345.com.example.app",\n "paths": [ "/*", "/some/path/*" ]\n }\n ]\n }\n}\n', + content_type="application/json", + ) # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.sites.well_known.put( + site_id="580e63e98c9a982ac9b8b741", + file_name="apple-app-site-association.txt", + file_data='{\n "applinks": {\n "apps": [],\n "details": [\n {\n "appID": "ABCDE12345.com.example.app",\n "paths": [ "/*", "/some/path/*" ]\n }\n ]\n }\n}\n', + content_type="application/json", + ) # type: ignore[func-returns-value] + is None + ) + + +async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.sites.well_known.delete(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.sites.well_known.delete(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) diff --git a/tests/test_access_groups.py b/tests/test_access_groups.py deleted file mode 100644 index dfe7e19..0000000 --- a/tests/test_access_groups.py +++ /dev/null @@ -1,49 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "count": 1, - "limit": 10, - "offset": 0, - "total": 1, - "accessGroups": [ - { - "id": "62be58d404be8a6cc900c081", - "name": "Research Team", - "shortId": "rt", - "slug": "hitchhikers-guide-research-team", - "createdOn": "2022-08-01T19:41:48Z", - }, - { - "id": "65a96161991e77bbb4a6c573", - "name": "Admin", - "shortId": "ad", - "slug": "admin", - "createdOn": "2022-08-01T19:41:48Z", - }, - ], - } - expected_types: typing.Any = { - "count": None, - "limit": None, - "offset": None, - "total": None, - "accessGroups": ( - "list", - { - 0: {"id": None, "name": None, "shortId": None, "slug": None, "createdOn": "datetime"}, - 1: {"id": None, "name": None, "shortId": None, "slug": None, "createdOn": "datetime"}, - }, - ), - } - response = client.access_groups.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.access_groups.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_assets.py b/tests/test_assets.py index af158ef..3ae051d 100644 --- a/tests/test_assets.py +++ b/tests/test_assets.py @@ -30,9 +30,33 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "quality": 100, } ], - "altText": "A red chair", - } - ] + "altText": "A single candy wrapper", + }, + { + "id": "63e5889e7fe4eafa7384cea5", + "contentType": "image/png", + "size": 2212772, + "siteId": "63938b302ea6b0aa6f3d8745", + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg", + "originalFileName": "Gum-Wrapper.svg", + "displayName": "63e5889e7fe4eafa7384cea5_Gum-Wrapper.png", + "lastUpdated": "2023-03-01T23:42:57Z", + "createdOn": "2023-02-09T23:58:22Z", + "variants": [ + { + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "originalFileName": "Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "displayName": "660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "format": "png", + "width": 500, + "height": 900, + "quality": 100, + } + ], + "altText": "A single gum wrapper", + }, + ], + "pagination": {"limit": 2, "offset": 0, "total": 2}, } expected_types: typing.Any = { "assets": ( @@ -63,14 +87,41 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: }, ), "altText": None, - } + }, + 1: { + "id": None, + "contentType": None, + "size": "integer", + "siteId": None, + "hostedUrl": None, + "originalFileName": None, + "displayName": None, + "lastUpdated": "datetime", + "createdOn": "datetime", + "variants": ( + "list", + { + 0: { + "hostedUrl": None, + "originalFileName": None, + "displayName": None, + "format": None, + "width": "integer", + "height": "integer", + "quality": "integer", + } + }, + ), + "altText": None, + }, }, - ) + ), + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } - response = client.assets.list(site_id="580e63e98c9a982ac9b8b741") + response = client.assets.list(site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) validate_response(response, expected_response, expected_types) - async_response = await async_client.assets.list(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.assets.list(site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) validate_response(async_response, expected_response, expected_types) @@ -94,7 +145,7 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "parentFolder": "6436b1ce5281cace05b65aea", "uploadUrl": "https://s3.amazonaws.com/webflow-dev-assets/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png", "assetUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d907ab9e91e3e9f56385e_paranoidAndroid-2024.png", - "hostedUrl": "https://d1otoma47x30pg.cloudfront.net/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png", + "hostedUrl": "https://dev-assets.website-files.com/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png", "originalFileName": "file.png", "createdOn": "2023-04-11T16:32:21Z", "lastUpdated": "2023-04-12T20:31:03Z", @@ -136,28 +187,28 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "55131cd036c09f7d07883dfc", + "id": "63e5889e7fe4eafa7384cea4", "contentType": "image/png", - "size": 1500, - "siteId": "62749158efef318abc8d5a0f", - "hostedUrl": "example.com/hostedimage.png", - "originalFileName": "image.png", - "displayName": "example-image-123.png", - "lastUpdated": "2016-09-06T21:12:22Z", - "createdOn": "2016-09-02T23:26:22Z", + "size": 2212772, + "siteId": "63938b302ea6b0aa6f3d8745", + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg", + "originalFileName": "Candy-Wrapper.svg", + "displayName": "63e5889e7fe4eafa7384cea4_Candy-Wrapper.png", + "lastUpdated": "2023-03-01T23:42:57Z", + "createdOn": "2023-02-09T23:58:22Z", "variants": [ { - "hostedUrl": "example.com/hostedimage.png", - "originalFileName": "image.png", - "displayName": "A brown dog", - "format": "format", - "width": 1500, + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "originalFileName": "Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "displayName": "660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "format": "png", + "width": 500, "height": 900, - "quality": 1, + "quality": 100, "error": "error", } ], - "altText": "A red chair", + "altText": "A single candy wrapper", } expected_types: typing.Any = { "id": None, @@ -208,28 +259,28 @@ async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "55131cd036c09f7d07883dfc", + "id": "63e5889e7fe4eafa7384cea4", "contentType": "image/png", - "size": 1500, - "siteId": "62749158efef318abc8d5a0f", - "hostedUrl": "example.com/hostedimage.png", - "originalFileName": "image.png", - "displayName": "example-image-123.png", - "lastUpdated": "2016-09-06T21:12:22Z", - "createdOn": "2016-09-02T23:26:22Z", + "size": 2212772, + "siteId": "63938b302ea6b0aa6f3d8745", + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg", + "originalFileName": "Candy-Wrapper.svg", + "displayName": "63e5889e7fe4eafa7384cea4_Candy-Wrapper.png", + "lastUpdated": "2023-03-01T23:42:57Z", + "createdOn": "2023-02-09T23:58:22Z", "variants": [ { - "hostedUrl": "example.com/hostedimage.png", - "originalFileName": "image.png", - "displayName": "A brown dog", - "format": "format", - "width": 1500, + "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "originalFileName": "Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "displayName": "660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", + "format": "png", + "width": 500, "height": 900, - "quality": 1, + "quality": 100, "error": "error", } ], - "altText": "A red chair", + "altText": "A single candy wrapper", } expected_types: typing.Any = { "id": None, @@ -295,7 +346,7 @@ async def test_list_folders(client: Webflow, async_client: AsyncWebflow) -> None } }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } response = client.assets.list_folders(site_id="580e63e98c9a982ac9b8b741") validate_response(response, expected_response, expected_types) diff --git a/tests/test_collections.py b/tests/test_collections.py index 1e76945..4494869 100644 --- a/tests/test_collections.py +++ b/tests/test_collections.py @@ -4,6 +4,9 @@ from webflow import AsyncWebflow import typing from .utilities import validate_response +from webflow import StaticField +from webflow import ReferenceField +from webflow import ReferenceFieldMetadata async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: @@ -75,22 +78,40 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "580e63fc8c9a982ac9b8b745", + "id": "562ac0395358780a1f5e6fbd", "displayName": "Blog Posts", "singularName": "Blog Post", - "slug": "post", + "slug": "posts", "createdOn": "2016-10-24T19:41:48Z", "lastUpdated": "2016-10-24T19:42:38Z", "fields": [ { - "id": "23cc2d952d4e4631ffd4345d2743db4e", + "id": "id", "isRequired": True, "isEditable": True, "type": "PlainText", - "slug": "name", - "displayName": "Name", - "helpText": "helpText", - } + "slug": "title", + "displayName": "Title", + "helpText": "The title of the blog post", + }, + { + "id": "id", + "isRequired": True, + "isEditable": True, + "type": "RichText", + "slug": "content", + "displayName": "Content", + "helpText": "The content of the blog post", + }, + { + "id": "id", + "isRequired": True, + "isEditable": True, + "type": "Reference", + "slug": "author", + "displayName": "Author", + "helpText": "The author of the blog post", + }, ], } expected_types: typing.Any = { @@ -111,39 +132,237 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "slug": None, "displayName": None, "helpText": None, - } + }, + 1: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 2: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, }, ), } response = client.collections.create( - site_id="580e63e98c9a982ac9b8b741", display_name="Blog Posts", singular_name="Blog Post", slug="posts" + site_id="580e63e98c9a982ac9b8b741", + display_name="Blog Posts", + singular_name="Blog Post", + slug="posts", + fields=[ + StaticField( + is_required=True, type="PlainText", display_name="Title", help_text="The title of the blog post" + ), + StaticField( + is_required=True, type="RichText", display_name="Content", help_text="The content of the blog post" + ), + ReferenceField( + is_required=True, + type="Reference", + display_name="Author", + help_text="The author of the blog post", + metadata=ReferenceFieldMetadata(collection_id="23cc2d952d4e4631ffd4345d2743db4e"), + ), + ], ) validate_response(response, expected_response, expected_types) async_response = await async_client.collections.create( - site_id="580e63e98c9a982ac9b8b741", display_name="Blog Posts", singular_name="Blog Post", slug="posts" + site_id="580e63e98c9a982ac9b8b741", + display_name="Blog Posts", + singular_name="Blog Post", + slug="posts", + fields=[ + StaticField( + is_required=True, type="PlainText", display_name="Title", help_text="The title of the blog post" + ), + StaticField( + is_required=True, type="RichText", display_name="Content", help_text="The content of the blog post" + ), + ReferenceField( + is_required=True, + type="Reference", + display_name="Author", + help_text="The author of the blog post", + metadata=ReferenceFieldMetadata(collection_id="23cc2d952d4e4631ffd4345d2743db4e"), + ), + ], ) validate_response(async_response, expected_response, expected_types) async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "580e63fc8c9a982ac9b8b745", - "displayName": "Blog Posts", - "singularName": "Blog Post", - "slug": "post", - "createdOn": "2016-10-24T19:41:48Z", - "lastUpdated": "2016-10-24T19:42:38Z", + "id": "7f15043107e2fc95644e93807ee25dd6", + "displayName": "Guide Entries", + "singularName": "Guide Entry", + "slug": "guide-entry", + "createdOn": "2024-04-12T12:42:00Z", + "lastUpdated": "2024-04-12T12:42:00Z", "fields": [ { - "id": "23cc2d952d4e4631ffd4345d2743db4e", + "id": "5e2a1b3c4d5e6f7890a1b2c3", "isRequired": True, "isEditable": True, "type": "PlainText", "slug": "name", - "displayName": "Name", + "displayName": "Entry Title", + "helpText": "Name of the entry.", + }, + { + "id": "5e2a1b3c4d5e6f7890a1b2c4", + "isRequired": True, + "isEditable": True, + "type": "PlainText", + "slug": "slug", + "displayName": "Slug", + "helpText": "Slug of the entry.", + }, + { + "id": "6f7e8d9c0b1a2e3d4c5b6a7f", + "isRequired": False, + "isEditable": True, + "type": "PlainText", + "slug": "summary", + "displayName": "Summary", + "helpText": "A short summary of the entry.", + }, + { + "id": "1a2b3c4d5e6f7a8b9c0d1e2f", + "isRequired": False, + "isEditable": True, + "type": "RichText", + "slug": "entry-html", + "displayName": "Entry HTML", + "helpText": "The HTML content of the entry.", + }, + { + "id": "7e8d9c0b1a2e3d4c5b6a7f8e", + "isRequired": False, + "isEditable": True, + "type": "Image", + "slug": "illustration-image", + "displayName": "Illustration Image", + "helpText": "An image of the entry.", + }, + { + "id": "2f3e4d5c6b7a8e9d0c1b2a3f", + "isRequired": False, + "isEditable": True, + "type": "VideoLink", + "slug": "demonstration-video", + "displayName": "Demonstration Video", + "helpText": "A video of the entry.", + }, + { + "id": "8e9d0c1b2a3f4e5d6c7b8a9e", + "isRequired": False, + "isEditable": True, + "type": "Link", + "slug": "more-info-link", + "displayName": "More Info Link", + "helpText": "A link to more information about the entry.", + }, + { + "id": "3f4e5d6c7b8a9e0d1c2b3a4f", + "isRequired": False, + "isEditable": True, + "type": "Number", + "slug": "importance-level", + "displayName": "Importance Level", + "helpText": "The importance level of the entry.", + }, + { + "id": "9e0d1c2b3a4f5e6d7c8b9a0e", + "isRequired": False, + "isEditable": True, + "type": "Switch", + "slug": "is-essential", + "displayName": "Is Essential", + "helpText": "Is this entry essential?", + }, + { + "id": "4f5e6d7c8b9a0e1d2c3b4a5f", + "isRequired": False, + "isEditable": True, + "type": "Color", + "slug": "first-mentioned", + "displayName": "First Mentioned", + "helpText": "Date of the first mention of the subject.", + }, + { + "id": "0e1d2c3b4a5f6e7d8c9b0a1e", + "isRequired": False, + "isEditable": True, + "type": "Color", + "slug": "towel-color", + "displayName": "Towel Color", + "helpText": "The color of the towel.", + }, + { + "id": "5f6e7d8c9b0a1e2d3c4b5a6f", + "isRequired": False, + "isEditable": True, + "type": "Reference", + "slug": "related-entry", + "displayName": "Related Entry", + "helpText": "A related entry.", + }, + { + "id": "1e2d3c4b5a6f7e8d9c0b1a2f", + "isRequired": False, + "isEditable": True, + "type": "MultiReference", + "slug": "mentioned-in-entries", + "displayName": "Mentioned In Entries", + "helpText": "Entries that mention this subject.", + }, + { + "id": "6f7e8d9c0b1a2e3d4c5b6a8f", + "isRequired": False, + "isEditable": True, + "type": "Option", + "slug": "item-type", + "displayName": "Item Type", + "helpText": "The type of item.", + }, + { + "id": "2e3d4c5b6a7f8e9d0c1b2a4f", + "isRequired": False, + "isEditable": True, + "type": "File", + "slug": "guide-file", + "displayName": "Guide File", "helpText": "helpText", - } + }, + { + "id": "7f8e9d0c1b2a3f4e5d6c8b9e", + "isRequired": False, + "isEditable": True, + "type": "Email", + "slug": "contributor-email", + "displayName": "Contributor Email", + "helpText": "helpText", + }, + { + "id": "3a4f5e6d7c8b9a0e1d2c4b5f", + "isRequired": False, + "isEditable": True, + "type": "Phone", + "slug": "emergency-contact", + "displayName": "Emergency Contact", + "helpText": "helpText", + }, ], } expected_types: typing.Any = { @@ -164,7 +383,151 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "slug": None, "displayName": None, "helpText": None, - } + }, + 1: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 2: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 3: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 4: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 5: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 6: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 7: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 8: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 9: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 10: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 11: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 12: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 13: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 14: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 15: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, + 16: { + "id": None, + "isRequired": None, + "isEditable": None, + "type": None, + "slug": None, + "displayName": None, + "helpText": None, + }, }, ), } diff --git a/tests/test_components.py b/tests/test_components.py index 2f5a42d..c502ef0 100644 --- a/tests/test_components.py +++ b/tests/test_components.py @@ -5,6 +5,10 @@ import typing from .utilities import validate_response from webflow import TextNodeWrite +from webflow import Select +from webflow import SelectNodeWriteChoicesItem +from webflow import TextInputNodeWrite +from webflow import SubmitButtonNodeWrite from webflow import ComponentInstanceNodePropertyOverridesWrite from webflow import ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem from webflow.resources.components import ComponentPropertiesWritePropertiesItem @@ -54,12 +58,16 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: 3: {"id": None, "name": None, "group": None, "description": None, "readonly": None}, }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } - response = client.components.list(site_id="580e63e98c9a982ac9b8b741") + response = client.components.list( + site_id="580e63e98c9a982ac9b8b741", branch_id="68026fa68ef6dc744c75b833", limit=1, offset=1 + ) validate_response(response, expected_response, expected_types) - async_response = await async_client.components.list(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.components.list( + site_id="580e63e98c9a982ac9b8b741", branch_id="68026fa68ef6dc744c75b833", limit=1, offset=1 + ) validate_response(async_response, expected_response, expected_types) @@ -67,53 +75,55 @@ async def test_get_content(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { "componentId": "69118560-d0bc-15fc-bbf8-b8fe5f6535b5", "nodes": [ + {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, + {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, + {"id": "id", "image": {}, "attributes": {"key": "value"}, "type": "image"}, + {"id": "id", "placeholder": "placeholder", "attributes": {"key": "value"}, "type": "text-input"}, { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad623", - "componentId": "nodes", - "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + "id": "id", + "choices": [{"value": "value", "text": "text"}], + "attributes": {"key": "value"}, + "type": "select", }, { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad627", - "componentId": "nodes", - "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + "id": "id", + "value": "value", + "waitingText": "waitingText", + "attributes": {"key": "value"}, + "type": "submit-button", }, { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad629", - "componentId": "nodes", + "id": "id", + "componentId": "componentId", "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], - }, - { "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad631", - "componentId": "6258612d1ee792848f805dcf", - "propertyOverrides": [ - { - "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad633", - "type": "Plain Text", - "text": {"text": "Don't Panic!"}, - }, - { - "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad635", - "type": "Rich Text", - "text": {"html": "

Always know where your towel is.

"}, - }, - ], }, ], - "pagination": {"limit": 4, "offset": 0, "total": 4}, + "pagination": {"limit": 7, "offset": 0, "total": 7}, } expected_types: typing.Any = { "componentId": None, - "nodes": ("list", {0: "no_validate", 1: "no_validate", 2: "no_validate", 3: "no_validate"}), - "pagination": {"limit": None, "offset": None, "total": None}, + "nodes": ( + "list", + { + 0: "no_validate", + 1: "no_validate", + 2: "no_validate", + 3: "no_validate", + 4: "no_validate", + 5: "no_validate", + 6: "no_validate", + }, + ), + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } response = client.components.get_content( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) validate_response(response, expected_response, expected_types) @@ -121,6 +131,9 @@ async def test_get_content(client: Webflow, async_client: AsyncWebflow) -> None: site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) validate_response(async_response, expected_response, expected_types) @@ -132,6 +145,7 @@ async def test_update_content(client: Webflow, async_client: AsyncWebflow) -> No site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", nodes=[ TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

" @@ -140,6 +154,17 @@ async def test_update_content(client: Webflow, async_client: AsyncWebflow) -> No node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Don't Panic!

Always know where your towel is.

", ), + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem(value="choice-1", text="First choice"), + SelectNodeWriteChoicesItem(value="choice-2", text="Second choice"), + ], + ), + TextInputNodeWrite(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", placeholder="Enter something here..."), + SubmitButtonNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", value="Submit", waiting_text="Submitting..." + ), ComponentInstanceNodePropertyOverridesWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ @@ -160,6 +185,7 @@ async def test_update_content(client: Webflow, async_client: AsyncWebflow) -> No site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", nodes=[ TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

" @@ -168,6 +194,17 @@ async def test_update_content(client: Webflow, async_client: AsyncWebflow) -> No node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Don't Panic!

Always know where your towel is.

", ), + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem(value="choice-1", text="First choice"), + SelectNodeWriteChoicesItem(value="choice-2", text="Second choice"), + ], + ), + TextInputNodeWrite(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", placeholder="Enter something here..."), + SubmitButtonNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", value="Submit", waiting_text="Submitting..." + ), ComponentInstanceNodePropertyOverridesWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ @@ -213,12 +250,15 @@ async def test_get_properties(client: Webflow, async_client: AsyncWebflow) -> No 1: {"propertyId": None, "type": None, "label": None, "text": {"html": None}}, }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } response = client.components.get_properties( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) validate_response(response, expected_response, expected_types) @@ -226,6 +266,9 @@ async def test_get_properties(client: Webflow, async_client: AsyncWebflow) -> No site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", + limit=1, + offset=1, ) validate_response(async_response, expected_response, expected_types) @@ -237,6 +280,7 @@ async def test_update_properties(client: Webflow, async_client: AsyncWebflow) -> site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", properties=[ ComponentPropertiesWritePropertiesItem( property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="The Hitchhiker’s Guide to the Galaxy" @@ -253,6 +297,7 @@ async def test_update_properties(client: Webflow, async_client: AsyncWebflow) -> site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", locale_id="65427cf400e02b306eaa04a0", + branch_id="68026fa68ef6dc744c75b833", properties=[ ComponentPropertiesWritePropertiesItem( property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="The Hitchhiker’s Guide to the Galaxy" diff --git a/tests/test_forms.py b/tests/test_forms.py index ee88977..8ca6e40 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -14,12 +14,13 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "createdOn": "2016-10-24T19:41:29Z", "lastUpdated": "2016-10-24T19:43:17Z", "fields": { - "0": {"displayName": "Email", "userVisible": True}, - "1": {"displayName": "Email", "userVisible": True}, + "0": {"displayName": "Email", "placeholder": "Enter your email", "userVisible": True}, + "1": {"displayName": "Email", "placeholder": "Enter your email", "userVisible": True}, }, "responseSettings": { "redirectUrl": "https://example.com", "redirectMethod": "GET", + "redirectAction": "POST https://example.com", "sendEmailConfirmation": True, }, "id": "589a331aa51e760df7ccb89e", @@ -34,10 +35,11 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "displayName": "Name Form", "createdOn": "2016-10-24T19:41:29Z", "lastUpdated": "2016-10-24T19:43:17Z", - "fields": {"0": {"displayName": "Email", "userVisible": True}}, + "fields": {"0": {"displayName": "Email", "placeholder": "Enter your email", "userVisible": True}}, "responseSettings": { "redirectUrl": "https://example.com", "redirectMethod": "GET", + "redirectAction": "POST https://example.com", "sendEmailConfirmation": False, }, "id": "580ff8d7ba3e45ba9fe588e9", @@ -62,11 +64,16 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "fields": ( "dict", { - 0: (None, {"displayName": None, "userVisible": None}), - 1: (None, {"displayName": None, "userVisible": None}), + 0: (None, {"displayName": None, "placeholder": None, "userVisible": None}), + 1: (None, {"displayName": None, "placeholder": None, "userVisible": None}), }, ), - "responseSettings": {"redirectUrl": None, "redirectMethod": None, "sendEmailConfirmation": None}, + "responseSettings": { + "redirectUrl": None, + "redirectMethod": None, + "redirectAction": None, + "sendEmailConfirmation": None, + }, "id": None, "siteId": None, "siteDomainId": None, @@ -79,8 +86,13 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "displayName": None, "createdOn": "datetime", "lastUpdated": "datetime", - "fields": ("dict", {0: (None, {"displayName": None, "userVisible": None})}), - "responseSettings": {"redirectUrl": None, "redirectMethod": None, "sendEmailConfirmation": None}, + "fields": ("dict", {0: (None, {"displayName": None, "placeholder": None, "userVisible": None})}), + "responseSettings": { + "redirectUrl": None, + "redirectMethod": None, + "redirectAction": None, + "sendEmailConfirmation": None, + }, "id": None, "siteId": None, "siteDomainId": None, @@ -91,12 +103,12 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: }, }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } - response = client.forms.list(site_id="580e63e98c9a982ac9b8b741") + response = client.forms.list(site_id="580e63e98c9a982ac9b8b741", limit=1, offset=1) validate_response(response, expected_response, expected_types) - async_response = await async_client.forms.list(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.forms.list(site_id="580e63e98c9a982ac9b8b741", limit=1, offset=1) validate_response(async_response, expected_response, expected_types) @@ -209,12 +221,12 @@ async def test_list_submissions(client: Webflow, async_client: AsyncWebflow) -> }, }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } - response = client.forms.list_submissions(form_id="580e63e98c9a982ac9b8b741") + response = client.forms.list_submissions(form_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) validate_response(response, expected_response, expected_types) - async_response = await async_client.forms.list_submissions(form_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.forms.list_submissions(form_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) validate_response(async_response, expected_response, expected_types) @@ -242,6 +254,19 @@ async def test_get_submission(client: Webflow, async_client: AsyncWebflow) -> No validate_response(async_response, expected_response, expected_types) +async def test_delete_submission(client: Webflow, async_client: AsyncWebflow) -> None: + # Type ignore to avoid mypy complaining about the function not being meant to return a value + assert ( + client.forms.delete_submission(form_submission_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + assert ( + await async_client.forms.delete_submission(form_submission_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] + is None + ) + + async def test_update_submission(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { "id": "6321ca84df3949bfc6752327", diff --git a/tests/test_inventory.py b/tests/test_inventory.py index a4f1518..95062f9 100644 --- a/tests/test_inventory.py +++ b/tests/test_inventory.py @@ -9,11 +9,11 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = {"id": "5bfedb42bab0ad90fa7dad39", "quantity": 100, "inventoryType": "finite"} expected_types: typing.Any = {"id": None, "quantity": None, "inventoryType": None} - response = client.inventory.list(collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754") + response = client.inventory.list(sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415") validate_response(response, expected_response, expected_types) async_response = await async_client.inventory.list( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754" + sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415" ) validate_response(async_response, expected_response, expected_types) @@ -22,11 +22,11 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = {"id": "5bfedb42bab0ad90fa7dad39", "quantity": 100, "inventoryType": "finite"} expected_types: typing.Any = {"id": None, "quantity": None, "inventoryType": None} response = client.inventory.update( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", inventory_type="infinite" + sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415", inventory_type="infinite" ) validate_response(response, expected_response, expected_types) async_response = await async_client.inventory.update( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", inventory_type="infinite" + sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415", inventory_type="infinite" ) validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_orders.py b/tests/test_orders.py index a874784..dce7836 100644 --- a/tests/test_orders.py +++ b/tests/test_orders.py @@ -20,9 +20,9 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "disputedOn": "2018-12-03T22:06:15Z", "disputeUpdatedOn": "2018-12-03T22:06:15Z", "disputeLastStatus": "warning_needs_response", - "customerPaid": {"unit": "USD", "value": "5892", "string": " 211.55 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": " 200.89 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": " 4.23 USD"}, + "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 211.55 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": "$ 200.89 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 4.23 USD"}, "allAddresses": [ { "type": "billing", @@ -73,7 +73,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "purchasedItems": [ { "count": 2, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 111.22 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 111.22 USD"}, "productId": "66072fb61b89448912e26791", "productName": "Luxurious Fresh Ball", "productSlug": "luxurious-fresh-ball", @@ -82,9 +82,9 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "weight": 11, "width": 82, "height": 70, @@ -92,7 +92,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: }, { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 83.09 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 83.09 USD"}, "productId": "66072fb61b89448912e2678b", "productName": "Incredible Bronze Towels", "productSlug": "incredible-bronze-towels", @@ -101,9 +101,10 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "incredible-bronze-towels-sleek-frozen-incredible-metal", "variantSKU": "incredible-bronze-towels-sleek-frozen-incredible-metal", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 83.09 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 83.09 USD"}, + "weight": 5, "width": 19, "height": 72, "length": 18, @@ -111,10 +112,12 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: ], "purchasedItemsCount": 3, "stripeDetails": { + "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", "paymentMethod": "pm_1P410gJYFi4lcbXWbeKghqjK", "paymentIntentId": "pi_3P410iJYFi4lcbXW0EKKgcVg", "customerId": "cus_Ptod8KJBiiPgnH", "chargeId": "ch_3P410iJYFi4lcbXW0DxUkzCH", + "refundReason": "requested_by_customer", }, "stripeCard": { "last4": "4242", @@ -142,7 +145,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "type": "tax", "name": "State Taxes", "description": "CA Taxes (6.25%)", - "price": {"unit": "USD", "value": "5892", "string": "3.44"}, + "price": {"unit": "USD", "value": "5892", "string": "$3.44"}, } ] }, @@ -165,9 +168,9 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "disputedOn": "2018-12-03T22:06:15Z", "disputeUpdatedOn": "2018-12-03T22:06:15Z", "disputeLastStatus": "warning_needs_response", - "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, "allAddresses": [ { "type": "billing", @@ -217,7 +220,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "purchasedItems": [ { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "productId": "66072fb61b89448912e26791", "productName": "Luxurious Fresh Ball", "productSlug": "luxurious-fresh-ball", @@ -226,9 +229,9 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "weight": 11, "width": 82, "height": 70, @@ -236,7 +239,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: }, { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "productId": "66072fb61b89448912e26799", "productName": "Recycled Steel Gloves", "productSlug": "recycled-steel-gloves", @@ -245,9 +248,9 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "weight": 38, "width": 76, "height": 85, @@ -256,6 +259,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: ], "purchasedItemsCount": 2, "stripeDetails": { + "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", "customerId": "cus_PpRsNHwWdUoRKR", @@ -284,28 +288,28 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "hasDownloads": False, "paymentProcessor": "stripe", "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, "extras": [ { "type": "tax", "name": "State Taxes", "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, }, { "type": "tax", "name": "City Taxes", "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, }, { "type": "shipping", "name": "Flat", "description": "", - "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, }, ], - "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, }, "downloadFiles": [ { @@ -418,6 +422,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "variantSKU": None, "variantImage": {"url": None}, "variantPrice": {"unit": None, "value": None, "string": None}, + "weight": None, "width": None, "height": None, "length": None, @@ -426,10 +431,12 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: ), "purchasedItemsCount": None, "stripeDetails": { + "subscriptionId": None, "paymentMethod": None, "paymentIntentId": None, "customerId": None, "chargeId": None, + "refundReason": None, }, "stripeCard": { "last4": None, @@ -570,6 +577,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: ), "purchasedItemsCount": None, "stripeDetails": { + "subscriptionId": None, "paymentMethod": None, "paymentIntentId": None, "customerId": None, @@ -628,12 +636,14 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: }, }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } - response = client.orders.list(site_id="580e63e98c9a982ac9b8b741") + response = client.orders.list(site_id="580e63e98c9a982ac9b8b741", status="pending", offset=1, limit=1) validate_response(response, expected_response, expected_types) - async_response = await async_client.orders.list(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.orders.list( + site_id="580e63e98c9a982ac9b8b741", status="pending", offset=1, limit=1 + ) validate_response(async_response, expected_response, expected_types) @@ -649,9 +659,9 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "disputedOn": "2024-03-29T21:29:21Z", "disputeUpdatedOn": "2024-03-29T21:29:21Z", "disputeLastStatus": "charge_refunded", - "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, "allAddresses": [ { "type": "billing", @@ -705,7 +715,7 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "purchasedItems": [ { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "productId": "66072fb61b89448912e26791", "productName": "Luxurious Fresh Ball", "productSlug": "luxurious-fresh-ball", @@ -714,9 +724,9 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "weight": 11, "width": 82, "height": 70, @@ -724,7 +734,7 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: }, { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "productId": "66072fb61b89448912e26799", "productName": "Recycled Steel Gloves", "productSlug": "recycled-steel-gloves", @@ -733,9 +743,9 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "weight": 38, "width": 76, "height": 85, @@ -774,28 +784,28 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "hasDownloads": False, "paymentProcessor": "stripe", "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, "extras": [ { "type": "tax", "name": "State Taxes", "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, }, { "type": "tax", "name": "City Taxes", "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, }, { "type": "shipping", "name": "Flat", "description": "", - "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, }, ], - "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, }, "downloadFiles": [ { @@ -987,9 +997,9 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "disputedOn": "2024-03-29T21:29:21Z", "disputeUpdatedOn": "2024-03-29T21:29:21Z", "disputeLastStatus": "charge_refunded", - "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, "allAddresses": [ { "type": "billing", @@ -1043,7 +1053,7 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "purchasedItems": [ { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "productId": "66072fb61b89448912e26791", "productName": "Luxurious Fresh Ball", "productSlug": "luxurious-fresh-ball", @@ -1052,9 +1062,9 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "weight": 11, "width": 82, "height": 70, @@ -1062,7 +1072,7 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: }, { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "productId": "66072fb61b89448912e26799", "productName": "Recycled Steel Gloves", "productSlug": "recycled-steel-gloves", @@ -1071,9 +1081,9 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "weight": 38, "width": 76, "height": 85, @@ -1112,28 +1122,28 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "hasDownloads": False, "paymentProcessor": "stripe", "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, "extras": [ { "type": "tax", "name": "State Taxes", "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, }, { "type": "tax", "name": "City Taxes", "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, }, { "type": "shipping", "name": "Flat", "description": "", - "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, }, ], - "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, }, "downloadFiles": [ { @@ -1325,9 +1335,9 @@ async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> No "disputedOn": "2024-03-29T21:29:21Z", "disputeUpdatedOn": "2024-03-29T21:29:21Z", "disputeLastStatus": "charge_refunded", - "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, "allAddresses": [ { "type": "billing", @@ -1381,7 +1391,7 @@ async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> No "purchasedItems": [ { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "productId": "66072fb61b89448912e26791", "productName": "Luxurious Fresh Ball", "productSlug": "luxurious-fresh-ball", @@ -1390,9 +1400,9 @@ async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> No "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "weight": 11, "width": 82, "height": 70, @@ -1400,7 +1410,7 @@ async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> No }, { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "productId": "66072fb61b89448912e26799", "productName": "Recycled Steel Gloves", "productSlug": "recycled-steel-gloves", @@ -1409,9 +1419,9 @@ async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> No "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "weight": 38, "width": 76, "height": 85, @@ -1450,28 +1460,28 @@ async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> No "hasDownloads": False, "paymentProcessor": "stripe", "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, "extras": [ { "type": "tax", "name": "State Taxes", "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, }, { "type": "tax", "name": "City Taxes", "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, }, { "type": "shipping", "name": "Flat", "description": "", - "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, }, ], - "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, }, "downloadFiles": [ { @@ -1663,9 +1673,9 @@ async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> "disputedOn": "2024-03-29T21:29:21Z", "disputeUpdatedOn": "2024-03-29T21:29:21Z", "disputeLastStatus": "charge_refunded", - "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, "allAddresses": [ { "type": "billing", @@ -1719,7 +1729,7 @@ async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> "purchasedItems": [ { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "productId": "66072fb61b89448912e26791", "productName": "Luxurious Fresh Ball", "productSlug": "luxurious-fresh-ball", @@ -1728,9 +1738,9 @@ async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "weight": 11, "width": 82, "height": 70, @@ -1738,7 +1748,7 @@ async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> }, { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "productId": "66072fb61b89448912e26799", "productName": "Recycled Steel Gloves", "productSlug": "recycled-steel-gloves", @@ -1747,9 +1757,9 @@ async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "weight": 38, "width": 76, "height": 85, @@ -1788,28 +1798,28 @@ async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> "hasDownloads": False, "paymentProcessor": "stripe", "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, "extras": [ { "type": "tax", "name": "State Taxes", "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, }, { "type": "tax", "name": "City Taxes", "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, }, { "type": "shipping", "name": "Flat", "description": "", - "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, }, ], - "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, }, "downloadFiles": [ { @@ -2001,9 +2011,9 @@ async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: "disputedOn": "2024-03-29T21:29:21Z", "disputeUpdatedOn": "2024-03-29T21:29:21Z", "disputeLastStatus": "charge_refunded", - "customerPaid": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": " 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": " 2.37 USD"}, + "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, + "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, + "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, "allAddresses": [ { "type": "billing", @@ -2057,7 +2067,7 @@ async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: "purchasedItems": [ { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "productId": "66072fb61b89448912e26791", "productName": "Luxurious Fresh Ball", "productSlug": "luxurious-fresh-ball", @@ -2066,9 +2076,9 @@ async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 55.61 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, "weight": 11, "width": 82, "height": 70, @@ -2076,7 +2086,7 @@ async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: }, { "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "productId": "66072fb61b89448912e26799", "productName": "Recycled Steel Gloves", "productSlug": "recycled-steel-gloves", @@ -2085,9 +2095,9 @@ async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", "variantImage": { - "url": "https://d1otoma47x30pg.cloudfront.net/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" + "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" }, - "variantPrice": {"unit": "USD", "value": "5892", "string": " 53.44 USD"}, + "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, "weight": 38, "width": 76, "height": 85, @@ -2126,28 +2136,28 @@ async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: "hasDownloads": False, "paymentProcessor": "stripe", "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": " 109.05 USD"}, + "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, "extras": [ { "type": "tax", "name": "State Taxes", "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": " 4.36 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, }, { "type": "tax", "name": "City Taxes", "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": " 5.32 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, }, { "type": "shipping", "name": "Flat", "description": "", - "price": {"unit": "USD", "value": "5892", "string": " 0.00 USD"}, + "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, }, ], - "total": {"unit": "USD", "value": "5892", "string": " 118.73 USD"}, + "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, }, "downloadFiles": [ { diff --git a/tests/test_pages.py b/tests/test_pages.py index 716c201..63003be 100644 --- a/tests/test_pages.py +++ b/tests/test_pages.py @@ -4,10 +4,13 @@ from webflow import AsyncWebflow import typing from .utilities import validate_response -import datetime -from webflow import PageSeo -from webflow import PageOpenGraph +from webflow.resources.pages import PageMetadataWriteSeo +from webflow.resources.pages import PageMetadataWriteOpenGraph from webflow import TextNodeWrite +from webflow import Select +from webflow import SelectNodeWriteChoicesItem +from webflow import TextInputNodeWrite +from webflow import SubmitButtonNodeWrite from webflow import ComponentInstanceNodePropertyOverridesWrite from webflow import ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem @@ -26,9 +29,9 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "2024-03-11T10:42:42Z", "archived": False, "draft": False, - "canBranch": True, - "isBranch": False, - "isMembersOnly": False, + "canBranch": False, + "isBranch": True, + "branchId": "68026fa68ef6dc744c75b833", "seo": { "title": "The Ultimate Hitchhiker's Guide to the Galaxy", "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", @@ -55,7 +58,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "draft": False, "canBranch": True, "isBranch": False, - "isMembersOnly": False, + "branchId": "68026fa68ef6dc744c75b833", "seo": { "title": "Celebrate Towel Day - The Hitchhiker's Guide to the Galaxy", "description": "A guide to celebrating Towel Day, in honor of the most massively useful thing an interstellar hitchhiker can have.", @@ -89,7 +92,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "draft": None, "canBranch": None, "isBranch": None, - "isMembersOnly": None, + "branchId": None, "seo": {"title": None, "description": None}, "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, "localeId": None, @@ -108,7 +111,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "draft": None, "canBranch": None, "isBranch": None, - "isMembersOnly": None, + "branchId": None, "seo": {"title": None, "description": None}, "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, "localeId": None, @@ -116,13 +119,15 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: }, }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } - response = client.pages.list(site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0") + response = client.pages.list( + site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0", limit=1, offset=1 + ) validate_response(response, expected_response, expected_types) async_response = await async_client.pages.list( - site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0" + site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0", limit=1, offset=1 ) validate_response(async_response, expected_response, expected_types) @@ -139,9 +144,9 @@ async def test_get_metadata(client: Webflow, async_client: AsyncWebflow) -> None "lastUpdated": "2024-03-11T10:42:42Z", "archived": False, "draft": False, - "canBranch": True, - "isBranch": False, - "isMembersOnly": False, + "canBranch": False, + "isBranch": True, + "branchId": "68026fa68ef6dc744c75b833", "seo": { "title": "The Ultimate Hitchhiker's Guide to the Galaxy", "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", @@ -168,7 +173,7 @@ async def test_get_metadata(client: Webflow, async_client: AsyncWebflow) -> None "draft": None, "canBranch": None, "isBranch": None, - "isMembersOnly": None, + "branchId": None, "seo": {"title": None, "description": None}, "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, "localeId": None, @@ -195,9 +200,9 @@ async def test_update_page_settings(client: Webflow, async_client: AsyncWebflow) "lastUpdated": "2024-03-11T10:42:42Z", "archived": False, "draft": False, - "canBranch": True, - "isBranch": False, - "isMembersOnly": False, + "canBranch": False, + "isBranch": True, + "branchId": "68026fa68ef6dc744c75b833", "seo": { "title": "The Ultimate Hitchhiker's Guide to the Galaxy", "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", @@ -224,7 +229,7 @@ async def test_update_page_settings(client: Webflow, async_client: AsyncWebflow) "draft": None, "canBranch": None, "isBranch": None, - "isMembersOnly": None, + "branchId": None, "seo": {"title": None, "description": None}, "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, "localeId": None, @@ -233,56 +238,36 @@ async def test_update_page_settings(client: Webflow, async_client: AsyncWebflow) response = client.pages.update_page_settings( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", title="Guide to the Galaxy", slug="guide-to-the-galaxy", - created_on=datetime.datetime.fromisoformat("2024-03-11 10:42:00+00:00"), - last_updated=datetime.datetime.fromisoformat("2024-03-11 10:42:42+00:00"), - archived=False, - draft=False, - can_branch=True, - is_branch=False, - seo=PageSeo( + seo=PageMetadataWriteSeo( title="The Ultimate Hitchhiker's Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", ), - open_graph=PageOpenGraph( + open_graph=PageMetadataWriteOpenGraph( title="Explore the Cosmos with The Ultimate Guide", title_copied=False, description="Dive deep into the mysteries of the universe with your guide to everything galactic.", description_copied=False, ), - page_locale_id="653fd9af6a07fc9cfd7a5e57", - published_path="/en-us/guide-to-the-galaxy", ) validate_response(response, expected_response, expected_types) async_response = await async_client.pages.update_page_settings( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", - id="6596da6045e56dee495bcbba", - site_id="6258612d1ee792848f805dcf", title="Guide to the Galaxy", slug="guide-to-the-galaxy", - created_on=datetime.datetime.fromisoformat("2024-03-11 10:42:00+00:00"), - last_updated=datetime.datetime.fromisoformat("2024-03-11 10:42:42+00:00"), - archived=False, - draft=False, - can_branch=True, - is_branch=False, - seo=PageSeo( + seo=PageMetadataWriteSeo( title="The Ultimate Hitchhiker's Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", ), - open_graph=PageOpenGraph( + open_graph=PageMetadataWriteOpenGraph( title="Explore the Cosmos with The Ultimate Guide", title_copied=False, description="Dive deep into the mysteries of the universe with your guide to everything galactic.", description_copied=False, ), - page_locale_id="653fd9af6a07fc9cfd7a5e57", - published_path="/en-us/guide-to-the-galaxy", ) validate_response(async_response, expected_response, expected_types) @@ -290,57 +275,54 @@ async def test_update_page_settings(client: Webflow, async_client: AsyncWebflow) async def test_get_content(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { "pageId": "658205daa3e8206a523b5ad4", + "branchId": "68026fa68ef6dc744c75b833", "nodes": [ + {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, + {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, + {"id": "id", "image": {}, "attributes": {"key": "value"}, "type": "image"}, { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad623", - "componentId": "nodes", - "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], + "id": "id", + "choices": [{"value": "value", "text": "text"}], + "attributes": {"key": "value"}, + "type": "select", }, + {"id": "id", "placeholder": "placeholder", "attributes": {"key": "value"}, "type": "text-input"}, + {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad627", - "componentId": "nodes", + "id": "id", + "componentId": "componentId", "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], - }, - { - "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad629", - "componentId": "nodes", - "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], - }, - { "type": "component-instance", - "id": "a245c12d-995b-55ee-5ec7-aa36a6cad631", - "componentId": "6258612d1ee792848f805dcf", - "propertyOverrides": [ - { - "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad633", - "type": "Plain Text", - "label": "Catchphrase", - "text": {"text": "Don't Panic!"}, - }, - { - "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad635", - "type": "Rich Text", - "label": "Tagline", - "text": {"html": "

Always know where your towel is.

"}, - }, - ], }, ], "pagination": {"limit": 4, "offset": 0, "total": 4}, + "lastUpdated": "2016-10-24T19:42:38Z", } expected_types: typing.Any = { "pageId": None, - "nodes": ("list", {0: "no_validate", 1: "no_validate", 2: "no_validate", 3: "no_validate"}), - "pagination": {"limit": None, "offset": None, "total": None}, + "branchId": None, + "nodes": ( + "list", + { + 0: "no_validate", + 1: "no_validate", + 2: "no_validate", + 3: "no_validate", + 4: "no_validate", + 5: "no_validate", + 6: "no_validate", + }, + ), + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, + "lastUpdated": "datetime", } - response = client.pages.get_content(page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0") + response = client.pages.get_content( + page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", limit=1, offset=1 + ) validate_response(response, expected_response, expected_types) async_response = await async_client.pages.get_content( - page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0" + page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", limit=1, offset=1 ) validate_response(async_response, expected_response, expected_types) @@ -359,6 +341,17 @@ async def test_update_static_content(client: Webflow, async_client: AsyncWebflow node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Don't Panic!

Always know where your towel is.

", ), + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem(value="choice-1", text="First choice"), + SelectNodeWriteChoicesItem(value="choice-2", text="Second choice"), + ], + ), + TextInputNodeWrite(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", placeholder="Enter something here..."), + SubmitButtonNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", value="Submit", waiting_text="Submitting..." + ), ComponentInstanceNodePropertyOverridesWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ @@ -386,6 +379,17 @@ async def test_update_static_content(client: Webflow, async_client: AsyncWebflow node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Don't Panic!

Always know where your towel is.

", ), + Select( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", + choices=[ + SelectNodeWriteChoicesItem(value="choice-1", text="First choice"), + SelectNodeWriteChoicesItem(value="choice-2", text="Second choice"), + ], + ), + TextInputNodeWrite(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", placeholder="Enter something here..."), + SubmitButtonNodeWrite( + node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", value="Submit", waiting_text="Submitting..." + ), ComponentInstanceNodePropertyOverridesWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", property_overrides=[ diff --git a/tests/test_products.py b/tests/test_products.py index 03d28db..3438763 100644 --- a/tests/test_products.py +++ b/tests/test_products.py @@ -4,7 +4,15 @@ from webflow import AsyncWebflow import typing from .utilities import validate_response +from webflow.resources.products import ProductSkuCreateProduct +from webflow import ProductFieldData +from webflow import SkuPropertyList +from webflow import SkuPropertyListEnumItem +from webflow.resources.products import ProductSkuCreateSku +from webflow import SkuFieldData +from webflow import SkuFieldDataPrice from webflow import Sku +import datetime async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: @@ -28,24 +36,32 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: { "id": "Color", "name": "Color", - "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}], + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], } ], }, }, "skus": [ { - "id": "580e63fc8c9a982ac9b8b745", + "id": "66072fb71b89448912e2681c", "cmsLocaleId": "653ad57de882f528b32e810e", "lastPublished": "2023-03-17T18:47:35Z", "lastUpdated": "2023-03-17T18:47:35Z", "createdOn": "2023-03-17T18:47:35Z", "fieldData": { - "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, - "name": "Blue T-shirt", - "slug": "t-shirt-blue", - "price": {"value": 100, "unit": "USD"}, - "quantity": 10, + "sku-values": {"color": "blue", "size": "small"}, + "name": "Colorful T-shirt - Default", + "slug": "colorful-t-shirt-default", + "price": {"value": 2499, "unit": "USD", "currency": "USD"}, + "main-image": "https://www.example.com/image.jpg", + "sku": "1234567890", + "sku-properties": [ + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } + ], }, } ], @@ -93,11 +109,22 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "createdOn": "datetime", "fieldData": { - "sku-values": ("dict", {0: (None, None)}), + "sku-values": ("dict", {0: (None, None), 1: (None, None)}), "name": None, "slug": None, - "price": {"value": None, "unit": None}, - "quantity": None, + "price": {"value": None, "unit": None, "currency": None}, + "main-image": None, + "sku": None, + "sku-properties": ( + "list", + { + 0: { + "id": None, + "name": None, + "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), + } + }, + ), }, } }, @@ -105,12 +132,12 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: } }, ), - "pagination": {"limit": None, "offset": None, "total": None}, + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } - response = client.products.list(site_id="580e63e98c9a982ac9b8b741") + response = client.products.list(site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) validate_response(response, expected_response, expected_types) - async_response = await async_client.products.list(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.products.list(site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) validate_response(async_response, expected_response, expected_types) @@ -130,9 +157,13 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "description": "A plain cotton t-shirt.", "shippable": True, "sku-properties": [ - {"id": "Color", "name": "Color", "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}]} + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } ], - "categories": ["categories"], + "category": ["category"], "tax-category": "standard-taxable", "default-sku": "default-sku", "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", @@ -140,17 +171,25 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: }, "skus": [ { - "id": "580e63fc8c9a982ac9b8b745", + "id": "66072fb71b89448912e2681c", "cmsLocaleId": "653ad57de882f528b32e810e", "lastPublished": "2023-03-17T18:47:35Z", "lastUpdated": "2023-03-17T18:47:35Z", "createdOn": "2023-03-17T18:47:35Z", "fieldData": { - "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, - "name": "Blue T-shirt", - "slug": "t-shirt-blue", - "price": {"value": 100, "unit": "USD"}, - "quantity": 10, + "sku-values": {"color": "blue", "size": "small"}, + "name": "Colorful T-shirt - Default", + "slug": "colorful-t-shirt-default", + "price": {"value": 2499, "unit": "USD", "currency": "USD"}, + "main-image": "https://www.example.com/image.jpg", + "sku": "1234567890", + "sku-properties": [ + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } + ], }, } ], @@ -173,7 +212,7 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "list", {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, ), - "categories": ("list", {0: None}), + "category": ("list", {0: None}), "tax-category": None, "default-sku": None, "ec-product-type": None, @@ -189,20 +228,107 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "createdOn": "datetime", "fieldData": { - "sku-values": ("dict", {0: (None, None)}), + "sku-values": ("dict", {0: (None, None), 1: (None, None)}), "name": None, "slug": None, - "price": {"value": None, "unit": None}, - "quantity": None, + "price": {"value": None, "unit": None, "currency": None}, + "main-image": None, + "sku": None, + "sku-properties": ( + "list", + { + 0: { + "id": None, + "name": None, + "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), + } + }, + ), }, } }, ), } - response = client.products.create(site_id="580e63e98c9a982ac9b8b741") + response = client.products.create( + site_id="580e63e98c9a982ac9b8b741", + publish_status="staging", + product=ProductSkuCreateProduct( + field_data=ProductFieldData( + name="Colorful T-shirt", + slug="colorful-t-shirt", + description="Our best-selling t-shirt available in multiple colors and sizes", + sku_properties=[ + SkuPropertyList( + id="color", + name="Color", + enum=[ + SkuPropertyListEnumItem(id="red", name="Red", slug="red"), + SkuPropertyListEnumItem(id="yellow", name="Yellow", slug="yellow"), + SkuPropertyListEnumItem(id="blue", name="Blue", slug="blue"), + ], + ), + SkuPropertyList( + id="size", + name="Size", + enum=[ + SkuPropertyListEnumItem(id="small", name="Small", slug="small"), + SkuPropertyListEnumItem(id="medium", name="Medium", slug="medium"), + SkuPropertyListEnumItem(id="large", name="Large", slug="large"), + ], + ), + ], + ) + ), + sku=ProductSkuCreateSku( + field_data=SkuFieldData( + name="Colorful T-shirt - Red Small", + slug="colorful-t-shirt-red-small", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", + ) + ), + ) validate_response(response, expected_response, expected_types) - async_response = await async_client.products.create(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.products.create( + site_id="580e63e98c9a982ac9b8b741", + publish_status="staging", + product=ProductSkuCreateProduct( + field_data=ProductFieldData( + name="Colorful T-shirt", + slug="colorful-t-shirt", + description="Our best-selling t-shirt available in multiple colors and sizes", + sku_properties=[ + SkuPropertyList( + id="color", + name="Color", + enum=[ + SkuPropertyListEnumItem(id="red", name="Red", slug="red"), + SkuPropertyListEnumItem(id="yellow", name="Yellow", slug="yellow"), + SkuPropertyListEnumItem(id="blue", name="Blue", slug="blue"), + ], + ), + SkuPropertyList( + id="size", + name="Size", + enum=[ + SkuPropertyListEnumItem(id="small", name="Small", slug="small"), + SkuPropertyListEnumItem(id="medium", name="Medium", slug="medium"), + SkuPropertyListEnumItem(id="large", name="Large", slug="large"), + ], + ), + ], + ) + ), + sku=ProductSkuCreateSku( + field_data=SkuFieldData( + name="Colorful T-shirt - Red Small", + slug="colorful-t-shirt-red-small", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", + ) + ), + ) validate_response(async_response, expected_response, expected_types) @@ -222,9 +348,13 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "description": "A plain cotton t-shirt.", "shippable": True, "sku-properties": [ - {"id": "Color", "name": "Color", "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}]} + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } ], - "categories": ["categories"], + "category": ["category"], "tax-category": "standard-taxable", "default-sku": "default-sku", "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", @@ -232,17 +362,25 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: }, "skus": [ { - "id": "580e63fc8c9a982ac9b8b745", + "id": "66072fb71b89448912e2681c", "cmsLocaleId": "653ad57de882f528b32e810e", "lastPublished": "2023-03-17T18:47:35Z", "lastUpdated": "2023-03-17T18:47:35Z", "createdOn": "2023-03-17T18:47:35Z", "fieldData": { - "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, - "name": "Blue T-shirt", - "slug": "t-shirt-blue", - "price": {"value": 100, "unit": "USD"}, - "quantity": 10, + "sku-values": {"color": "blue", "size": "small"}, + "name": "Colorful T-shirt - Default", + "slug": "colorful-t-shirt-default", + "price": {"value": 2499, "unit": "USD", "currency": "USD"}, + "main-image": "https://www.example.com/image.jpg", + "sku": "1234567890", + "sku-properties": [ + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } + ], }, } ], @@ -265,7 +403,7 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "list", {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, ), - "categories": ("list", {0: None}), + "category": ("list", {0: None}), "tax-category": None, "default-sku": None, "ec-product-type": None, @@ -281,11 +419,22 @@ async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "createdOn": "datetime", "fieldData": { - "sku-values": ("dict", {0: (None, None)}), + "sku-values": ("dict", {0: (None, None), 1: (None, None)}), "name": None, "slug": None, - "price": {"value": None, "unit": None}, - "quantity": None, + "price": {"value": None, "unit": None, "currency": None}, + "main-image": None, + "sku": None, + "sku-properties": ( + "list", + { + 0: { + "id": None, + "name": None, + "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), + } + }, + ), }, } }, @@ -315,9 +464,13 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "description": "A plain cotton t-shirt.", "shippable": True, "sku-properties": [ - {"id": "Color", "name": "Color", "enum": [{"id": "id", "name": "Royal Blue", "slug": "royal-blue"}]} + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } ], - "categories": ["categories"], + "category": ["category"], "tax-category": "standard-taxable", "default-sku": "default-sku", "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", @@ -340,7 +493,7 @@ async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: "list", {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, ), - "categories": ("list", {0: None}), + "category": ("list", {0: None}), "tax-category": None, "default-sku": None, "ec-product-type": None, @@ -359,17 +512,25 @@ async def test_create_sku(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { "skus": [ { - "id": "580e63fc8c9a982ac9b8b745", + "id": "66072fb71b89448912e2681c", "cmsLocaleId": "653ad57de882f528b32e810e", "lastPublished": "2023-03-17T18:47:35Z", "lastUpdated": "2023-03-17T18:47:35Z", "createdOn": "2023-03-17T18:47:35Z", "fieldData": { - "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, - "name": "Blue T-shirt", - "slug": "t-shirt-blue", - "price": {"value": 100, "unit": "USD"}, - "quantity": 10, + "sku-values": {"color": "blue", "size": "small"}, + "name": "Colorful T-shirt - Default", + "slug": "colorful-t-shirt-default", + "price": {"value": 2499, "unit": "USD", "currency": "USD"}, + "main-image": "https://www.example.com/image.jpg", + "sku": "1234567890", + "sku-properties": [ + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } + ], }, } ] @@ -385,44 +546,92 @@ async def test_create_sku(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "createdOn": "datetime", "fieldData": { - "sku-values": ("dict", {0: (None, None)}), + "sku-values": ("dict", {0: (None, None), 1: (None, None)}), "name": None, "slug": None, - "price": {"value": None, "unit": None}, - "quantity": None, + "price": {"value": None, "unit": None, "currency": None}, + "main-image": None, + "sku": None, + "sku-properties": ( + "list", + { + 0: { + "id": None, + "name": None, + "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), + } + }, + ), }, } }, ) } response = client.products.create_sku( - site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", skus=[Sku()] + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + skus=[ + Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + ), + ) + ], ) validate_response(response, expected_response, expected_types) async_response = await async_client.products.create_sku( - site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", skus=[Sku()] + site_id="580e63e98c9a982ac9b8b741", + product_id="580e63fc8c9a982ac9b8b745", + skus=[ + Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + ), + ) + ], ) validate_response(async_response, expected_response, expected_types) async def test_update_sku(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "id": "580e63fc8c9a982ac9b8b745", + "id": "66072fb71b89448912e2681c", "cmsLocaleId": "653ad57de882f528b32e810e", "lastPublished": "2023-03-17T18:47:35Z", "lastUpdated": "2023-03-17T18:47:35Z", "createdOn": "2023-03-17T18:47:35Z", "fieldData": { - "sku-values": {"ff42fee0113744f693a764e3431a9cc2": "64a74715c456e36762fc39a1"}, - "name": "Blue T-shirt", - "slug": "t-shirt-blue", - "price": {"value": 100, "unit": "USD"}, + "sku-values": {"color": "blue", "size": "small"}, + "name": "Colorful T-shirt - Default", + "slug": "colorful-t-shirt-default", + "price": {"value": 2499, "unit": "USD", "currency": "USD"}, "compare-at-price": {"value": 100, "unit": "USD"}, "ec-sku-billing-method": "one-time", "ec-sku-subscription-plan": {"interval": "day", "frequency": 1, "trial": 7, "plans": [{}]}, - "track-inventory": True, - "quantity": 10, + "main-image": "https://www.example.com/image.jpg", + "sku": "1234567890", + "sku-properties": [ + { + "id": "Color", + "name": "Color", + "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], + } + ], }, } expected_types: typing.Any = { @@ -432,10 +641,10 @@ async def test_update_sku(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "datetime", "createdOn": "datetime", "fieldData": { - "sku-values": ("dict", {0: (None, None)}), + "sku-values": ("dict", {0: (None, None), 1: (None, None)}), "name": None, "slug": None, - "price": {"value": None, "unit": None}, + "price": {"value": None, "unit": None, "currency": None}, "compare-at-price": {"value": None, "unit": None}, "ec-sku-billing-method": None, "ec-sku-subscription-plan": { @@ -444,15 +653,30 @@ async def test_update_sku(client: Webflow, async_client: AsyncWebflow) -> None: "trial": None, "plans": ("list", {0: {}}), }, - "track-inventory": None, - "quantity": None, + "main-image": None, + "sku": None, + "sku-properties": ( + "list", + {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, + ), }, } response = client.products.update_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", sku_id="5e8518516e147040726cc415", - sku=Sku(), + sku=Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + ), + ), ) validate_response(response, expected_response, expected_types) @@ -460,6 +684,17 @@ async def test_update_sku(client: Webflow, async_client: AsyncWebflow) -> None: site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", sku_id="5e8518516e147040726cc415", - sku=Sku(), + sku=Sku( + id="66072fb71b89448912e2681c", + cms_locale_id="653ad57de882f528b32e810e", + last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), + field_data=SkuFieldData( + name="Colorful T-shirt - Default", + slug="colorful-t-shirt-default", + price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), + ), + ), ) validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 6432530..f81f7fc 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -39,7 +39,8 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "lastUpdated": "lastUpdated", "version": "1.0.0", }, - ] + ], + "pagination": {"limit": 100, "offset": 0, "total": 3}, } expected_types: typing.Any = { "registeredScripts": ( @@ -76,7 +77,8 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "version": None, }, }, - ) + ), + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } response = client.scripts.list(site_id="580e63e98c9a982ac9b8b741") validate_response(response, expected_response, expected_types) diff --git a/tests/test_sites.py b/tests/test_sites.py index 6e9dd9b..d1fc7bc 100644 --- a/tests/test_sites.py +++ b/tests/test_sites.py @@ -11,11 +11,11 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: "id": "670ecf86817e3cc7a510eb6a", "workspaceId": "625860a7a6c16d624927122f", "createdOn": "2024-10-15T20:24:38Z", - "displayName": "The Hitchiker‘s Guide", + "displayName": "The Hitchiker's Guide", "shortName": "hitchikers-guide", "lastPublished": "2016-10-24T19:43:17Z", "lastUpdated": "2024-10-15T20:24:38Z", - "previewUrl": "https://d1otoma47x30pg.cloudfront.net/580e63e98c9a982ac9b8b741/201610241243.png", + "previewUrl": "https://dev-assets.website-files.com/580e63e98c9a982ac9b8b741/201610241243.png", "timeZone": "America/Los_Angeles", "parentFolderId": "670ece123598db72d9648be1", "customDomains": [ @@ -44,7 +44,7 @@ async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: } ], }, - "dataCollectionEnabled": False, + "dataCollectionEnabled": True, "dataCollectionType": "always", } expected_types: typing.Any = { @@ -108,7 +108,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "shortName": "heart-of-gold", "lastPublished": "2023-04-02T12:42:00Z", "lastUpdated": "2016-10-24T19:43:17Z", - "previewUrl": "https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b741/197910121200.png", + "previewUrl": "https://dev-assets.website-files.com/42e63e98c9a982ac9b8b741/197910121200.png", "timeZone": "DeepSpace/InfiniteImprobability", "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", "customDomains": [ @@ -160,7 +160,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "shortName": "paranoid-android", "lastPublished": "2023-04-02T12:45:00Z", "lastUpdated": "2016-10-24T19:43:17Z", - "previewUrl": "https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b742/198110121200.png", + "previewUrl": "https://dev-assets.website-files.com/42e63e98c9a982ac9b8b742/198110121200.png", "timeZone": "DeepSpace/Depression", "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", "customDomains": [ @@ -199,7 +199,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "shortName": "vogon-poetry", "lastPublished": "2023-04-02T12:50:00Z", "lastUpdated": "2016-10-24T19:43:17Z", - "previewUrl": "https://d1otoma47x30pg.cloudfront.net/42e63e98c9a982ac9b8b743/198210121200.png", + "previewUrl": "https://dev-assets.website-files.com/42e63e98c9a982ac9b8b743/198210121200.png", "timeZone": "Vogsphere/PoetryHall", "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", "customDomains": [ @@ -630,8 +630,16 @@ async def test_publish(client: Webflow, async_client: AsyncWebflow) -> None: "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), "publishToWebflowSubdomain": None, } - response = client.sites.publish(site_id="580e63e98c9a982ac9b8b741") + response = client.sites.publish( + site_id="580e63e98c9a982ac9b8b741", + custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], + publish_to_webflow_subdomain=False, + ) validate_response(response, expected_response, expected_types) - async_response = await async_client.sites.publish(site_id="580e63e98c9a982ac9b8b741") + async_response = await async_client.sites.publish( + site_id="580e63e98c9a982ac9b8b741", + custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], + publish_to_webflow_subdomain=False, + ) validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_token.py b/tests/test_token.py index d57ee3b..d81bdea 100644 --- a/tests/test_token.py +++ b/tests/test_token.py @@ -57,7 +57,7 @@ async def test_introspect(client: Webflow, async_client: AsyncWebflow) -> None: "userIds": ("list", {0: None}), }, }, - "application": None, + "application": {"id": None, "description": None, "homepage": None, "displayName": None}, } response = client.token.introspect() validate_response(response, expected_response, expected_types) diff --git a/tests/test_users.py b/tests/test_users.py deleted file mode 100644 index abcbfd6..0000000 --- a/tests/test_users.py +++ /dev/null @@ -1,301 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response -from webflow.resources.users import UsersUpdateRequestData - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "count": 5, - "limit": 5, - "offset": 0, - "total": 201, - "users": [ - { - "id": "6287ec36a841b25637c663df", - "isEmailVerified": False, - "lastUpdated": "2022-05-20T13:46:12Z", - "invitedOn": "2016-10-24T19:41:29Z", - "createdOn": "2022-05-20T13:46:12Z", - "lastLogin": "2016-10-24T19:41:29Z", - "status": "unverified", - "accessGroups": [{"slug": "vogon-construction-crew", "type": "admin"}], - }, - { - "id": "6287ec36a841b25637c663f0", - "isEmailVerified": False, - "lastUpdated": "2022-05-19T05:32:04Z", - "invitedOn": "2016-10-24T19:41:29Z", - "createdOn": "2022-05-19T05:32:04Z", - "lastLogin": "2016-10-24T19:41:29Z", - "status": "unverified", - "accessGroups": [{"slug": "improbability-drive-test-subjects", "type": "admin"}], - }, - { - "id": "6287ec36a841b25637c663d9", - "isEmailVerified": True, - "lastUpdated": "2022-05-17T03:34:06Z", - "invitedOn": "2016-10-24T19:41:29Z", - "createdOn": "2022-05-17T03:34:06Z", - "lastLogin": "2016-10-24T19:41:29Z", - "status": "verified", - "accessGroups": [{"slug": "heart-of-gold-crew", "type": "admin"}], - }, - { - "id": "6287ec37a841b25637c6641b", - "isEmailVerified": False, - "lastUpdated": "2022-05-15T03:46:09Z", - "invitedOn": "2016-10-24T19:41:29Z", - "createdOn": "2022-05-15T03:46:09Z", - "lastLogin": "2016-10-24T19:41:29Z", - "status": "unverified", - "accessGroups": [{"slug": "hitchhikers-guide-research-team", "type": "admin"}], - }, - { - "id": "6287ec37a841b25637c66449", - "isEmailVerified": True, - "lastUpdated": "2022-05-15T02:55:38Z", - "invitedOn": "2016-10-24T19:41:29Z", - "createdOn": "2022-05-15T02:55:38Z", - "lastLogin": "2016-10-24T19:41:29Z", - "status": "verified", - "accessGroups": [{"slug": "milliways-reservationists", "type": "admin"}], - }, - ], - } - expected_types: typing.Any = { - "count": None, - "limit": None, - "offset": None, - "total": None, - "users": ( - "list", - { - 0: { - "id": None, - "isEmailVerified": None, - "lastUpdated": "datetime", - "invitedOn": "datetime", - "createdOn": "datetime", - "lastLogin": "datetime", - "status": None, - "accessGroups": ("list", {0: {"slug": None, "type": None}}), - }, - 1: { - "id": None, - "isEmailVerified": None, - "lastUpdated": "datetime", - "invitedOn": "datetime", - "createdOn": "datetime", - "lastLogin": "datetime", - "status": None, - "accessGroups": ("list", {0: {"slug": None, "type": None}}), - }, - 2: { - "id": None, - "isEmailVerified": None, - "lastUpdated": "datetime", - "invitedOn": "datetime", - "createdOn": "datetime", - "lastLogin": "datetime", - "status": None, - "accessGroups": ("list", {0: {"slug": None, "type": None}}), - }, - 3: { - "id": None, - "isEmailVerified": None, - "lastUpdated": "datetime", - "invitedOn": "datetime", - "createdOn": "datetime", - "lastLogin": "datetime", - "status": None, - "accessGroups": ("list", {0: {"slug": None, "type": None}}), - }, - 4: { - "id": None, - "isEmailVerified": None, - "lastUpdated": "datetime", - "invitedOn": "datetime", - "createdOn": "datetime", - "lastLogin": "datetime", - "status": None, - "accessGroups": ("list", {0: {"slug": None, "type": None}}), - }, - }, - ), - } - response = client.users.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.users.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "6287ec36a841b25637c663df", - "isEmailVerified": True, - "lastUpdated": "2022-05-20T13:46:12Z", - "invitedOn": "2022-05-20T13:46:12Z", - "createdOn": "2022-05-20T13:46:12Z", - "lastLogin": "2022-05-20T13:46:12Z", - "status": "verified", - "accessGroups": [{"slug": "webflowers", "type": "admin"}], - "data": { - "data": { - "name": "name", - "email": "email", - "accept-privacy": True, - "accept-communications": True, - "additionalProperties": "additionalProperties", - } - }, - } - expected_types: typing.Any = { - "id": None, - "isEmailVerified": None, - "lastUpdated": "datetime", - "invitedOn": "datetime", - "createdOn": "datetime", - "lastLogin": "datetime", - "status": None, - "accessGroups": ("list", {0: {"slug": None, "type": None}}), - "data": { - "data": { - "name": None, - "email": None, - "accept-privacy": None, - "accept-communications": None, - "additionalProperties": None, - } - }, - } - response = client.users.get(site_id="580e63e98c9a982ac9b8b741", user_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.users.get( - site_id="580e63e98c9a982ac9b8b741", user_id="580e63e98c9a982ac9b8b741" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.users.delete(site_id="580e63e98c9a982ac9b8b741", user_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.users.delete(site_id="580e63e98c9a982ac9b8b741", user_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] - is None - ) - - -async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "6287ec36a841b25637c663df", - "isEmailVerified": True, - "lastUpdated": "2022-05-20T13:46:12Z", - "invitedOn": "2022-05-20T13:46:12Z", - "createdOn": "2022-05-20T13:46:12Z", - "lastLogin": "2022-05-20T13:46:12Z", - "status": "verified", - "accessGroups": [{"slug": "webflowers", "type": "admin"}], - "data": { - "data": { - "name": "name", - "email": "email", - "accept-privacy": True, - "accept-communications": True, - "additionalProperties": "additionalProperties", - } - }, - } - expected_types: typing.Any = { - "id": None, - "isEmailVerified": None, - "lastUpdated": "datetime", - "invitedOn": "datetime", - "createdOn": "datetime", - "lastLogin": "datetime", - "status": None, - "accessGroups": ("list", {0: {"slug": None, "type": None}}), - "data": { - "data": { - "name": None, - "email": None, - "accept-privacy": None, - "accept-communications": None, - "additionalProperties": None, - } - }, - } - response = client.users.update( - site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", - data=UsersUpdateRequestData(name="Some One", accept_privacy=False, accept_communications=False), - access_groups=["webflowers", "platinum", "free-tier"], - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.users.update( - site_id="580e63e98c9a982ac9b8b741", - user_id="580e63e98c9a982ac9b8b741", - data=UsersUpdateRequestData(name="Some One", accept_privacy=False, accept_communications=False), - access_groups=["webflowers", "platinum", "free-tier"], - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_invite(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "6287ec36a841b25637c663df", - "isEmailVerified": True, - "lastUpdated": "2022-05-20T13:46:12Z", - "invitedOn": "2022-05-20T13:46:12Z", - "createdOn": "2022-05-20T13:46:12Z", - "lastLogin": "2022-05-20T13:46:12Z", - "status": "verified", - "accessGroups": [{"slug": "webflowers", "type": "admin"}], - "data": { - "data": { - "name": "name", - "email": "email", - "accept-privacy": True, - "accept-communications": True, - "additionalProperties": "additionalProperties", - } - }, - } - expected_types: typing.Any = { - "id": None, - "isEmailVerified": None, - "lastUpdated": "datetime", - "invitedOn": "datetime", - "createdOn": "datetime", - "lastLogin": "datetime", - "status": None, - "accessGroups": ("list", {0: {"slug": None, "type": None}}), - "data": { - "data": { - "name": None, - "email": None, - "accept-privacy": None, - "accept-communications": None, - "additionalProperties": None, - } - }, - } - response = client.users.invite( - site_id="580e63e98c9a982ac9b8b741", email="some.one@home.com", access_groups=["webflowers"] - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.users.invite( - site_id="580e63e98c9a982ac9b8b741", email="some.one@home.com", access_groups=["webflowers"] - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py index 4c19188..ea9884c 100644 --- a/tests/test_webhooks.py +++ b/tests/test_webhooks.py @@ -9,7 +9,6 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: expected_response: typing.Any = { - "pagination": {"limit": 100, "offset": 0, "total": 100}, "webhooks": [ { "id": "57ca0a9e418c504a6e1acbb6", @@ -42,9 +41,9 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: "createdOn": "2016-07-19T01:43:40Z", }, ], + "pagination": {"limit": 100, "offset": 0, "total": 100}, } expected_types: typing.Any = { - "pagination": {"limit": None, "offset": None, "total": None}, "webhooks": ( "list", { @@ -80,6 +79,7 @@ async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: }, }, ), + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, } response = client.webhooks.list(site_id="580e63e98c9a982ac9b8b741") validate_response(response, expected_response, expected_types) diff --git a/tests/workspaces/__init__.py b/tests/workspaces/__init__.py new file mode 100644 index 0000000..f3ea265 --- /dev/null +++ b/tests/workspaces/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/tests/workspaces/test_audit_logs.py b/tests/workspaces/test_audit_logs.py new file mode 100644 index 0000000..eb7ea27 --- /dev/null +++ b/tests/workspaces/test_audit_logs.py @@ -0,0 +1,61 @@ +# This file was auto-generated by Fern from our API Definition. + +from webflow import Webflow +from webflow import AsyncWebflow +import typing +import datetime +from ..utilities import validate_response + + +async def test_get_workspace_audit_logs(client: Webflow, async_client: AsyncWebflow) -> None: + expected_response: typing.Any = { + "items": [ + { + "eventSubType": "login", + "eventType": "user_access", + "timestamp": "2025-04-29T20:30:06Z", + "actor": {"id": "6661ccb359b561c69f29d554", "email": "someone@email.com"}, + "workspace": {"id": "6621ccb459b561c69f29d57c", "slug": "hitchhikers-workspace"}, + }, + { + "eventSubType": "user_added", + "eventType": "workspace_membership", + "timestamp": "2025-04-30T20:30:06Z", + "actor": {"id": "60492e55bbddce079561cd7a", "email": "someone@webflow.com"}, + "workspace": {"id": "6621ccb459b561c69f29d57c", "slug": "hitchhikers-workspace"}, + }, + { + "eventSubType": "user_added", + "eventType": "site_membership", + "timestamp": "2025-04-30T00:33:31Z", + "actor": {"id": "671fe00d185fc8c1ad409d37", "email": "someone@webflow.com"}, + "workspace": {"id": "6621ccb459b561c69f29d57c", "slug": "hitchhikers-workspace"}, + }, + ], + "pagination": {"limit": 10, "offset": 0, "total": 3}, + } + expected_types: typing.Any = { + "items": ("list", {0: "no_validate", 1: "no_validate", 2: "no_validate"}), + "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, + } + response = client.workspaces.audit_logs.get_workspace_audit_logs( + workspace_id_or_slug="hitchhikers-workspace", + limit=1, + offset=1, + sort_order="asc", + event_type="user_access", + from_=datetime.datetime.fromisoformat("2025-06-22 16:00:31+00:00"), + to=datetime.datetime.fromisoformat("2025-07-22 16:00:31+00:00"), + ) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.workspaces.audit_logs.get_workspace_audit_logs( + workspace_id_or_slug="hitchhikers-workspace", + limit=1, + offset=1, + sort_order="asc", + event_type="user_access", + from_=datetime.datetime.fromisoformat("2025-06-22 16:00:31+00:00"), + to=datetime.datetime.fromisoformat("2025-07-22 16:00:31+00:00"), + ) + validate_response(async_response, expected_response, expected_types) From 4ce764ab3d1ae7de4aacb30997a90773860f5353 Mon Sep 17 00:00:00 2001 From: Fern Support <126544928+fern-support@users.noreply.github.com> Date: Wed, 4 Mar 2026 22:29:28 -0500 Subject: [PATCH 11/13] Upgrade CI workflow to Ubuntu 24.04 Updated CI workflow to use Ubuntu 24.04 and modified test command path. --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14569f6..d396980 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: ci on: [push] jobs: compile: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Checkout repo uses: actions/checkout@v3 @@ -19,7 +19,7 @@ jobs: - name: Compile run: poetry run mypy . test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Checkout repo uses: actions/checkout@v3 @@ -36,12 +36,12 @@ jobs: - name: Install Fern run: npm install -g fern-api - name: Test - run: fern test --command "poetry run pytest -rP ." + run: fern test --command "poetry run pytest -rP ./tests/custom/" publish: needs: [compile, test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Checkout repo uses: actions/checkout@v3 From f171623b76556a42d073628307f9026ec92f503e Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 21:05:55 +0000 Subject: [PATCH 12/13] SDK regeneration --- .fern/metadata.json | 14 + .github/workflows/ci.yml | 28 +- .gitignore | 4 +- .mock/definition/__package__.yml | 4311 ----------------- .mock/definition/api.yml | 18 - .mock/definition/assets.yml | 487 -- .mock/definition/collections.yml | 350 -- .mock/definition/collections/fields.yml | 212 - .mock/definition/collections/items.yml | 2145 -------- .mock/definition/comments.yml | 41 - .mock/definition/components.yml | 548 --- .mock/definition/ecommerce.yml | 45 - .mock/definition/forms.yml | 399 -- .mock/definition/inventory.yml | 152 - .mock/definition/items.yml | 112 - .mock/definition/orders.yml | 1971 -------- .mock/definition/pages.yml | 611 --- .mock/definition/pages/scripts.yml | 155 - .mock/definition/products.yml | 642 --- .mock/definition/scripts.yml | 236 - .mock/definition/sites.yml | 558 --- .mock/definition/sites/activityLogs.yml | 77 - .mock/definition/sites/comments.yml | 352 -- .mock/definition/sites/forms.yml | 316 -- .mock/definition/sites/plans.yml | 48 - .mock/definition/sites/redirects.yml | 221 - .mock/definition/sites/robotsTxt.yml | 229 - .mock/definition/sites/scripts.yml | 243 - .mock/definition/sites/wellKnown.yml | 130 - .mock/definition/token.yml | 75 - .mock/definition/webhooks.yml | 188 - .mock/definition/workspaces/auditLogs.yml | 126 - .mock/fern.config.json | 4 - LICENSE | 21 + poetry.lock | 143 +- pyproject.toml | 43 +- reference.md | 1534 +++--- requirements.txt | 4 + src/webflow/__init__.py | 964 ++-- src/webflow/client.py | 369 +- src/webflow/core/__init__.py | 116 +- src/webflow/core/api_error.py | 18 +- src/webflow/core/client_wrapper.py | 66 +- src/webflow/core/datetime_utils.py | 42 + src/webflow/core/force_multipart.py | 18 + src/webflow/core/http_client.py | 581 ++- src/webflow/core/http_response.py | 59 + src/webflow/core/http_sse/__init__.py | 42 + src/webflow/core/http_sse/_api.py | 112 + src/webflow/core/http_sse/_decoders.py | 61 + .../webflow/core/http_sse/_exceptions.py | 5 + src/webflow/core/http_sse/_models.py | 17 + src/webflow/core/jsonable_encoder.py | 9 +- src/webflow/core/logging.py | 107 + src/webflow/core/parse_error.py | 36 + src/webflow/core/pydantic_utilities.py | 513 +- src/webflow/core/serialization.py | 10 +- src/webflow/errors/__init__.py | 51 +- src/webflow/errors/bad_request_error.py | 7 +- src/webflow/errors/conflict_error.py | 7 +- src/webflow/errors/forbidden_error.py | 7 +- src/webflow/errors/internal_server_error.py | 6 +- src/webflow/errors/not_found_error.py | 6 +- src/webflow/errors/too_many_requests_error.py | 6 +- src/webflow/errors/unauthorized_error.py | 6 +- src/webflow/resources/__init__.py | 119 +- src/webflow/resources/assets/__init__.py | 2 + src/webflow/resources/assets/client.py | 1233 +---- src/webflow/resources/assets/raw_client.py | 1805 +++++++ src/webflow/resources/collections/__init__.py | 99 +- src/webflow/resources/collections/client.py | 698 +-- .../resources/collections/raw_client.py | 917 ++++ .../collections/resources/__init__.py | 97 +- .../collections/resources/fields/__init__.py | 2 + .../collections/resources/fields/client.py | 507 +- .../resources/fields/raw_client.py | 732 +++ .../collections/resources/items/__init__.py | 93 +- .../collections/resources/items/client.py | 2755 +---------- .../collections/resources/items/raw_client.py | 4246 ++++++++++++++++ .../resources/items/types/__init__.py | 91 +- ...collection_item_request_body_field_data.py | 7 +- ..._item_request_body_field_data_one_item.py} | 10 +- .../resources/items/types/item_i_ds.py | 12 +- .../items/types/item_i_ds_with_locales.py | 6 +- .../items_create_item_live_request_body.py | 1 + .../types/items_create_item_request_body.py | 1 + ...ms_delete_items_live_request_items_item.py | 17 +- .../items_delete_items_request_items_item.py | 17 +- .../items/types/items_publish_item_request.py | 1 + ...s_publish_item_request_items_items_item.py | 17 +- .../types/items_publish_item_response.py | 12 +- .../types/items_update_items_response.py | 1 + .../resources/items/types/multiple_items.py | 6 +- .../items/types/multiple_live_items.py | 6 +- .../resources/items/types/single_cms_item.py | 8 +- src/webflow/resources/components/__init__.py | 46 +- src/webflow/resources/components/client.py | 897 +--- .../resources/components/raw_client.py | 1417 ++++++ .../resources/components/types/__init__.py | 42 +- .../types/component_dom_write_nodes_item.py | 7 +- ...ponent_properties_write_properties_item.py | 20 +- .../components_update_content_response.py | 4 +- .../components_update_properties_response.py | 4 +- src/webflow/resources/ecommerce/__init__.py | 2 + src/webflow/resources/ecommerce/client.py | 225 +- src/webflow/resources/ecommerce/raw_client.py | 278 ++ src/webflow/resources/forms/__init__.py | 2 + src/webflow/resources/forms/client.py | 1105 +---- src/webflow/resources/forms/raw_client.py | 1532 ++++++ src/webflow/resources/inventory/__init__.py | 34 +- src/webflow/resources/inventory/client.py | 431 +- src/webflow/resources/inventory/raw_client.py | 598 +++ .../resources/inventory/types/__init__.py | 36 +- .../types/ecomm_inventory_changed_payload.py | 12 +- src/webflow/resources/orders/__init__.py | 31 +- src/webflow/resources/orders/client.py | 1205 +---- src/webflow/resources/orders/raw_client.py | 1712 +++++++ .../resources/orders/types/__init__.py | 36 +- src/webflow/resources/pages/__init__.py | 44 +- src/webflow/resources/pages/client.py | 917 +--- src/webflow/resources/pages/raw_client.py | 1365 ++++++ .../resources/pages/resources/__init__.py | 31 +- .../pages/resources/scripts/__init__.py | 2 + .../pages/resources/scripts/client.py | 495 +- .../pages/resources/scripts/raw_client.py | 716 +++ src/webflow/resources/pages/types/__init__.py | 42 +- .../pages/types/page_dom_write_nodes_item.py | 7 +- .../types/page_metadata_write_open_graph.py | 30 +- .../pages/types/page_metadata_write_seo.py | 4 +- .../types/update_static_content_response.py | 4 +- src/webflow/resources/products/__init__.py | 35 +- src/webflow/resources/products/client.py | 1242 +---- src/webflow/resources/products/raw_client.py | 1791 +++++++ .../resources/products/types/__init__.py | 39 +- .../types/product_sku_create_product.py | 14 +- .../products/types/product_sku_create_sku.py | 14 +- .../types/products_create_sku_response.py | 6 +- src/webflow/resources/scripts/__init__.py | 2 + src/webflow/resources/scripts/client.py | 529 +- src/webflow/resources/scripts/raw_client.py | 801 +++ src/webflow/resources/sites/__init__.py | 82 +- src/webflow/resources/sites/client.py | 1287 +---- src/webflow/resources/sites/raw_client.py | 1587 ++++++ .../resources/sites/resources/__init__.py | 65 +- .../sites/resources/activity_logs/__init__.py | 2 + .../sites/resources/activity_logs/client.py | 170 +- .../resources/activity_logs/raw_client.py | 243 + .../sites/resources/comments/__init__.py | 52 +- .../sites/resources/comments/client.py | 545 +-- .../sites/resources/comments/raw_client.py | 876 ++++ .../resources/comments/types/__init__.py | 48 +- .../sites/resources/forms/__init__.py | 2 + .../resources/sites/resources/forms/client.py | 923 +--- .../sites/resources/forms/raw_client.py | 1330 +++++ .../sites/resources/plans/__init__.py | 2 + .../resources/sites/resources/plans/client.py | 183 +- .../sites/resources/plans/raw_client.py | 236 + .../sites/resources/redirects/__init__.py | 2 + .../sites/resources/redirects/client.py | 643 +-- .../sites/resources/redirects/raw_client.py | 978 ++++ .../sites/resources/robots_txt/__init__.py | 2 + .../sites/resources/robots_txt/client.py | 652 +-- .../sites/resources/robots_txt/raw_client.py | 987 ++++ .../sites/resources/scripts/__init__.py | 2 + .../sites/resources/scripts/client.py | 626 +-- .../sites/resources/scripts/raw_client.py | 946 ++++ .../sites/resources/well_known/__init__.py | 31 +- .../sites/resources/well_known/client.py | 339 +- .../sites/resources/well_known/raw_client.py | 507 ++ .../resources/well_known/types/__init__.py | 31 +- src/webflow/resources/sites/types/__init__.py | 31 +- .../sites/types/sites_publish_response.py | 29 +- src/webflow/resources/token/__init__.py | 2 + src/webflow/resources/token/client.py | 183 +- src/webflow/resources/token/raw_client.py | 261 + src/webflow/resources/webhooks/__init__.py | 2 + src/webflow/resources/webhooks/client.py | 644 +-- src/webflow/resources/webhooks/raw_client.py | 932 ++++ src/webflow/resources/workspaces/__init__.py | 43 +- src/webflow/resources/workspaces/client.py | 57 +- .../resources/workspaces/raw_client.py | 13 + .../workspaces/resources/__init__.py | 40 +- .../resources/audit_logs/__init__.py | 34 +- .../workspaces/resources/audit_logs/client.py | 216 +- .../resources/audit_logs/raw_client.py | 310 ++ .../resources/audit_logs/types/__init__.py | 36 +- src/webflow/types/__init__.py | 891 ++-- src/webflow/types/application.py | 15 +- src/webflow/types/asset.py | 99 +- src/webflow/types/asset_folder.py | 65 +- src/webflow/types/asset_folder_list.py | 20 +- src/webflow/types/asset_upload.py | 104 +- .../types/asset_upload_upload_details.py | 34 +- src/webflow/types/asset_variant.py | 38 +- src/webflow/types/assets.py | 6 +- src/webflow/types/authorization.py | 6 +- .../types/authorization_authorization.py | 58 +- ...thorization_authorization_authorized_to.py | 37 +- src/webflow/types/authorized_user.py | 27 +- src/webflow/types/bad_request_error_body.py | 1 + src/webflow/types/bulk_collection_item.py | 80 +- .../types/bulk_collection_item_field_data.py | 4 +- src/webflow/types/collection.py | 55 +- src/webflow/types/collection_item.py | 80 +- src/webflow/types/collection_item_changed.py | 18 +- src/webflow/types/collection_item_created.py | 18 +- .../types/collection_item_field_data.py | 6 +- src/webflow/types/collection_item_list.py | 6 +- .../collection_item_list_no_pagination.py | 6 +- .../types/collection_item_list_pagination.py | 4 +- .../types/collection_item_patch_single.py | 80 +- ...collection_item_patch_single_field_data.py | 4 +- .../types/collection_item_post_single.py | 80 +- .../collection_item_post_single_field_data.py | 6 +- .../types/collection_item_published.py | 20 +- src/webflow/types/collection_item_removed.py | 20 +- .../types/collection_item_removed_payload.py | 80 +- ...lection_item_removed_payload_field_data.py | 4 +- .../types/collection_item_unpublished.py | 20 +- .../collection_item_unpublished_payload.py | 80 +- ...ion_item_unpublished_payload_field_data.py | 4 +- .../types/collection_item_with_id_input.py | 82 +- ...ollection_item_with_id_input_field_data.py | 4 +- src/webflow/types/collection_list.py | 6 +- .../types/collection_list_array_item.py | 58 +- src/webflow/types/comment.py | 20 +- src/webflow/types/comment_payload.py | 126 +- src/webflow/types/comment_payload_author.py | 18 +- .../comment_payload_mentioned_users_item.py | 18 +- src/webflow/types/comment_reply.py | 90 +- src/webflow/types/comment_reply_author.py | 6 +- src/webflow/types/comment_reply_list.py | 6 +- .../types/comment_reply_list_pagination.py | 6 +- .../comment_reply_mentioned_users_item.py | 6 +- src/webflow/types/comment_thread.py | 88 +- src/webflow/types/comment_thread_author.py | 18 +- src/webflow/types/comment_thread_list.py | 6 +- .../types/comment_thread_list_pagination.py | 6 +- .../comment_thread_mentioned_users_item.py | 18 +- src/webflow/types/component.py | 6 +- src/webflow/types/component_dom.py | 22 +- ..._instance_node_property_overrides_write.py | 25 +- ...overrides_write_property_overrides_item.py | 24 +- src/webflow/types/component_list.py | 6 +- src/webflow/types/component_node.py | 28 +- src/webflow/types/component_properties.py | 20 +- src/webflow/types/component_property.py | 20 +- src/webflow/types/conflict.py | 2 +- src/webflow/types/custom_code_block.py | 57 +- .../types/custom_code_hosted_response.py | 84 +- .../types/custom_code_inline_response.py | 84 +- src/webflow/types/custom_role.py | 31 +- .../types/custom_role_audit_log_item.py | 14 +- src/webflow/types/dom.py | 46 +- src/webflow/types/domain.py | 19 +- src/webflow/types/domains.py | 14 +- src/webflow/types/ecommerce_settings.py | 45 +- src/webflow/types/error.py | 20 +- src/webflow/types/field.py | 48 +- src/webflow/types/field_create.py | 3 +- src/webflow/types/field_validations.py | 14 +- ...field_validations_additional_properties.py | 1 + ...tional_properties_additional_properties.py | 12 +- src/webflow/types/forbidden_error_body.py | 1 + src/webflow/types/form.py | 127 +- src/webflow/types/form_field.py | 1 + src/webflow/types/form_field_value.py | 31 +- src/webflow/types/form_list.py | 6 +- src/webflow/types/form_response_settings.py | 57 +- src/webflow/types/form_submission.py | 63 +- src/webflow/types/form_submission_list.py | 14 +- src/webflow/types/form_submission_trigger.py | 20 +- .../types/form_submission_trigger_payload.py | 63 +- ..._submission_trigger_payload_schema_item.py | 41 +- src/webflow/types/image_node.py | 6 +- src/webflow/types/image_node_image.py | 10 +- src/webflow/types/invalid_domain.py | 2 +- src/webflow/types/invalid_scopes.py | 2 +- src/webflow/types/inventory_item.py | 15 +- ..._list_items_live_request_last_published.py | 6 +- ...items_list_items_request_last_published.py | 6 +- src/webflow/types/list_custom_code_blocks.py | 6 +- src/webflow/types/locale.py | 42 +- src/webflow/types/locales.py | 6 +- src/webflow/types/metadata.py | 6 +- src/webflow/types/metadata_options_item.py | 6 +- src/webflow/types/new_order.py | 20 +- src/webflow/types/no_domains.py | 2 +- src/webflow/types/node.py | 28 +- src/webflow/types/not_enterprise_plan_site.py | 2 +- .../types/not_enterprise_plan_workspace.py | 2 +- src/webflow/types/option_field.py | 48 +- src/webflow/types/order.py | 355 +- src/webflow/types/order_address.py | 56 +- src/webflow/types/order_billing_address.py | 56 +- src/webflow/types/order_customer_info.py | 20 +- .../types/order_download_files_item.py | 4 +- src/webflow/types/order_list.py | 6 +- src/webflow/types/order_metadata.py | 12 +- src/webflow/types/order_price.py | 4 +- src/webflow/types/order_purchased_item.py | 118 +- .../order_purchased_item_variant_image.py | 4 +- ...order_purchased_item_variant_image_file.py | 42 +- ...d_item_variant_image_file_variants_item.py | 10 +- src/webflow/types/order_shipping_address.py | 56 +- src/webflow/types/order_totals.py | 6 +- src/webflow/types/order_totals_extras_item.py | 6 +- src/webflow/types/page.py | 152 +- src/webflow/types/page_created_webhook.py | 20 +- .../types/page_created_webhook_payload.py | 30 +- src/webflow/types/page_deleted_webhook.py | 20 +- .../types/page_deleted_webhook_payload.py | 30 +- src/webflow/types/page_list.py | 6 +- .../types/page_metadata_updated_webhook.py | 20 +- .../page_metadata_updated_webhook_payload.py | 30 +- src/webflow/types/page_open_graph.py | 30 +- src/webflow/types/page_seo.py | 4 +- src/webflow/types/pagination.py | 4 +- src/webflow/types/payload.py | 80 +- src/webflow/types/payload_field_data.py | 4 +- src/webflow/types/paypal_details.py | 79 +- src/webflow/types/product.py | 82 +- src/webflow/types/product_and_sk_us.py | 6 +- src/webflow/types/product_and_sk_us_list.py | 6 +- src/webflow/types/product_field_data.py | 54 +- src/webflow/types/redirect.py | 27 +- src/webflow/types/redirects.py | 6 +- src/webflow/types/reference_field.py | 50 +- src/webflow/types/reference_field_metadata.py | 17 +- src/webflow/types/registered_script_list.py | 14 +- src/webflow/types/robots.py | 6 +- src/webflow/types/robots_rules_item.py | 18 +- src/webflow/types/script_apply.py | 8 +- src/webflow/types/script_apply_list.py | 29 +- src/webflow/types/scripts.py | 1 + src/webflow/types/search_button_node.py | 6 +- src/webflow/types/search_button_node_write.py | 16 +- src/webflow/types/select.py | 16 +- src/webflow/types/select_node.py | 6 +- src/webflow/types/select_node_choices_item.py | 6 +- .../types/select_node_write_choices_item.py | 6 +- src/webflow/types/setting_change.py | 10 +- .../types/setting_change_audit_log_item.py | 12 +- .../types/single_locale_created_payload.py | 74 +- ...ingle_locale_created_payload_field_data.py | 4 +- src/webflow/types/site.py | 141 +- src/webflow/types/site_activity_log_item.py | 38 +- .../types/site_activity_log_item_user.py | 10 +- .../types/site_activity_log_response.py | 8 +- src/webflow/types/site_membership.py | 54 +- .../types/site_membership_audit_log_item.py | 14 +- src/webflow/types/site_plan.py | 19 +- src/webflow/types/site_publish.py | 20 +- src/webflow/types/site_publish_payload.py | 43 +- src/webflow/types/sites.py | 6 +- src/webflow/types/sku.py | 58 +- src/webflow/types/sku_field_data.py | 73 +- .../types/sku_field_data_compare_at_price.py | 4 +- ...sku_field_data_ec_sku_subscription_plan.py | 6 +- ...ata_ec_sku_subscription_plan_plans_item.py | 4 +- src/webflow/types/sku_field_data_price.py | 4 +- src/webflow/types/sku_property_list.py | 6 +- .../types/sku_property_list_enum_item.py | 6 +- src/webflow/types/static_field.py | 47 +- src/webflow/types/stripe_card.py | 32 +- src/webflow/types/stripe_card_expires.py | 4 +- src/webflow/types/stripe_details.py | 105 +- src/webflow/types/submit_button_node.py | 16 +- src/webflow/types/submit_button_node_write.py | 27 +- src/webflow/types/text.py | 4 +- src/webflow/types/text_input_node.py | 6 +- src/webflow/types/text_input_node_write.py | 16 +- src/webflow/types/text_node.py | 6 +- src/webflow/types/text_node_text.py | 4 +- src/webflow/types/text_node_write.py | 16 +- src/webflow/types/updated_order.py | 20 +- src/webflow/types/user_access.py | 17 +- .../types/user_access_audit_log_item.py | 14 +- src/webflow/types/webhook.py | 61 +- src/webflow/types/webhook_filter.py | 4 +- src/webflow/types/webhook_list.py | 8 +- src/webflow/types/workspace_audit_log_item.py | 96 +- .../types/workspace_audit_log_item_actor.py | 4 +- ...payload_site_membership_granular_access.py | 4 +- ...t_log_item_payload_site_membership_site.py | 4 +- ...tem_payload_site_membership_target_user.py | 4 +- ...ayload_workspace_invitation_target_user.py | 4 +- ..._workspace_invitation_target_users_item.py | 4 +- ...ayload_workspace_membership_target_user.py | 4 +- .../workspace_audit_log_item_workspace.py | 4 +- .../types/workspace_audit_log_response.py | 8 +- src/webflow/types/workspace_invitation.py | 51 +- .../workspace_invitation_audit_log_item.py | 14 +- src/webflow/types/workspace_membership.py | 45 +- .../workspace_membership_audit_log_item.py | 14 +- tests/collections/__init__.py | 2 - tests/collections/test_fields.py | 106 - tests/collections/test_items.py | 1068 ---- tests/conftest.py | 31 - tests/custom/test_client.py | 2 +- tests/pages/__init__.py | 2 - tests/pages/test_scripts.py | 85 - tests/sites/__init__.py | 2 - tests/sites/test_activity_logs.py | 53 - tests/sites/test_comments.py | 242 - tests/sites/test_forms.py | 193 - tests/sites/test_plans.py | 20 - tests/sites/test_redirects.py | 88 - tests/sites/test_robots_txt.py | 145 - tests/sites/test_scripts.py | 156 - tests/sites/test_well_known.py | 40 - tests/test_assets.py | 409 -- tests/test_collections.py | 551 --- tests/test_components.py | 311 -- tests/test_ecommerce.py | 20 - tests/test_forms.py | 291 -- tests/test_inventory.py | 32 - tests/test_orders.py | 2337 --------- tests/test_pages.py | 407 -- tests/test_products.py | 700 --- tests/test_scripts.py | 159 - tests/test_sites.py | 645 --- tests/test_token.py | 66 - tests/test_webhooks.py | 175 - tests/utilities.py | 162 - tests/utils/assets/models/__init__.py | 2 +- tests/utils/assets/models/circle.py | 2 +- .../assets/models/object_with_defaults.py | 1 - .../models/object_with_optional_field.py | 9 +- tests/utils/assets/models/shape.py | 6 +- tests/utils/assets/models/square.py | 2 +- .../assets/models/undiscriminated_shape.py | 1 + tests/utils/test_http_client.py | 249 +- tests/utils/test_query_encoding.py | 3 +- tests/utils/test_serialization.py | 6 +- tests/workspaces/__init__.py | 2 - tests/workspaces/test_audit_logs.py | 61 - 437 files changed, 37489 insertions(+), 45792 deletions(-) create mode 100644 .fern/metadata.json delete mode 100644 .mock/definition/__package__.yml delete mode 100644 .mock/definition/api.yml delete mode 100644 .mock/definition/assets.yml delete mode 100644 .mock/definition/collections.yml delete mode 100644 .mock/definition/collections/fields.yml delete mode 100644 .mock/definition/collections/items.yml delete mode 100644 .mock/definition/comments.yml delete mode 100644 .mock/definition/components.yml delete mode 100644 .mock/definition/ecommerce.yml delete mode 100644 .mock/definition/forms.yml delete mode 100644 .mock/definition/inventory.yml delete mode 100644 .mock/definition/items.yml delete mode 100644 .mock/definition/orders.yml delete mode 100644 .mock/definition/pages.yml delete mode 100644 .mock/definition/pages/scripts.yml delete mode 100644 .mock/definition/products.yml delete mode 100644 .mock/definition/scripts.yml delete mode 100644 .mock/definition/sites.yml delete mode 100644 .mock/definition/sites/activityLogs.yml delete mode 100644 .mock/definition/sites/comments.yml delete mode 100644 .mock/definition/sites/forms.yml delete mode 100644 .mock/definition/sites/plans.yml delete mode 100644 .mock/definition/sites/redirects.yml delete mode 100644 .mock/definition/sites/robotsTxt.yml delete mode 100644 .mock/definition/sites/scripts.yml delete mode 100644 .mock/definition/sites/wellKnown.yml delete mode 100644 .mock/definition/token.yml delete mode 100644 .mock/definition/webhooks.yml delete mode 100644 .mock/definition/workspaces/auditLogs.yml delete mode 100644 .mock/fern.config.json create mode 100644 LICENSE create mode 100644 requirements.txt create mode 100644 src/webflow/core/force_multipart.py create mode 100644 src/webflow/core/http_response.py create mode 100644 src/webflow/core/http_sse/__init__.py create mode 100644 src/webflow/core/http_sse/_api.py create mode 100644 src/webflow/core/http_sse/_decoders.py rename tests/__init__.py => src/webflow/core/http_sse/_exceptions.py (51%) create mode 100644 src/webflow/core/http_sse/_models.py create mode 100644 src/webflow/core/logging.py create mode 100644 src/webflow/core/parse_error.py create mode 100644 src/webflow/resources/assets/raw_client.py create mode 100644 src/webflow/resources/collections/raw_client.py create mode 100644 src/webflow/resources/collections/resources/fields/raw_client.py create mode 100644 src/webflow/resources/collections/resources/items/raw_client.py rename src/webflow/resources/collections/resources/items/types/{create_bulk_collection_item_request_body_field_data_item.py => create_bulk_collection_item_request_body_field_data_one_item.py} (73%) create mode 100644 src/webflow/resources/components/raw_client.py create mode 100644 src/webflow/resources/ecommerce/raw_client.py create mode 100644 src/webflow/resources/forms/raw_client.py create mode 100644 src/webflow/resources/inventory/raw_client.py create mode 100644 src/webflow/resources/orders/raw_client.py create mode 100644 src/webflow/resources/pages/raw_client.py create mode 100644 src/webflow/resources/pages/resources/scripts/raw_client.py create mode 100644 src/webflow/resources/products/raw_client.py create mode 100644 src/webflow/resources/scripts/raw_client.py create mode 100644 src/webflow/resources/sites/raw_client.py create mode 100644 src/webflow/resources/sites/resources/activity_logs/raw_client.py create mode 100644 src/webflow/resources/sites/resources/comments/raw_client.py create mode 100644 src/webflow/resources/sites/resources/forms/raw_client.py create mode 100644 src/webflow/resources/sites/resources/plans/raw_client.py create mode 100644 src/webflow/resources/sites/resources/redirects/raw_client.py create mode 100644 src/webflow/resources/sites/resources/robots_txt/raw_client.py create mode 100644 src/webflow/resources/sites/resources/scripts/raw_client.py create mode 100644 src/webflow/resources/sites/resources/well_known/raw_client.py create mode 100644 src/webflow/resources/token/raw_client.py create mode 100644 src/webflow/resources/webhooks/raw_client.py create mode 100644 src/webflow/resources/workspaces/raw_client.py create mode 100644 src/webflow/resources/workspaces/resources/audit_logs/raw_client.py delete mode 100644 tests/collections/__init__.py delete mode 100644 tests/collections/test_fields.py delete mode 100644 tests/collections/test_items.py delete mode 100644 tests/conftest.py delete mode 100644 tests/pages/__init__.py delete mode 100644 tests/pages/test_scripts.py delete mode 100644 tests/sites/__init__.py delete mode 100644 tests/sites/test_activity_logs.py delete mode 100644 tests/sites/test_comments.py delete mode 100644 tests/sites/test_forms.py delete mode 100644 tests/sites/test_plans.py delete mode 100644 tests/sites/test_redirects.py delete mode 100644 tests/sites/test_robots_txt.py delete mode 100644 tests/sites/test_scripts.py delete mode 100644 tests/sites/test_well_known.py delete mode 100644 tests/test_assets.py delete mode 100644 tests/test_collections.py delete mode 100644 tests/test_components.py delete mode 100644 tests/test_ecommerce.py delete mode 100644 tests/test_forms.py delete mode 100644 tests/test_inventory.py delete mode 100644 tests/test_orders.py delete mode 100644 tests/test_pages.py delete mode 100644 tests/test_products.py delete mode 100644 tests/test_scripts.py delete mode 100644 tests/test_sites.py delete mode 100644 tests/test_token.py delete mode 100644 tests/test_webhooks.py delete mode 100644 tests/utilities.py delete mode 100644 tests/workspaces/__init__.py delete mode 100644 tests/workspaces/test_audit_logs.py diff --git a/.fern/metadata.json b/.fern/metadata.json new file mode 100644 index 0000000..c585311 --- /dev/null +++ b/.fern/metadata.json @@ -0,0 +1,14 @@ +{ + "cliVersion": "4.22.0", + "generatorName": "fernapi/fern-python-sdk", + "generatorVersion": "4.63.4", + "generatorConfig": { + "client_class_name": "Webflow", + "improved_imports": false, + "pydantic_config": { + "use_str_enums": false + } + }, + "originGitCommit": "3ad89f5558f1774e8535f034a87bfe8c2fdfcd50", + "sdkVersion": "1.2.1" +} \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d396980..bab604b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,16 +1,20 @@ name: ci - on: [push] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + jobs: compile: - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - name: Bootstrap poetry run: | curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 @@ -19,36 +23,34 @@ jobs: - name: Compile run: poetry run mypy . test: - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - name: Bootstrap poetry run: | curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 - name: Install dependencies run: poetry install - - name: Install Fern - run: npm install -g fern-api - name: Test - run: fern test --command "poetry run pytest -rP ./tests/custom/" + run: poetry run pytest -rP -n auto . publish: needs: [compile, test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - name: Checkout repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - name: Bootstrap poetry run: | curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 diff --git a/.gitignore b/.gitignore index 0da665f..d2e4ca8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -dist/ .mypy_cache/ +.ruff_cache/ __pycache__/ +dist/ poetry.toml -.ruff_cache/ diff --git a/.mock/definition/__package__.yml b/.mock/definition/__package__.yml deleted file mode 100644 index 250c1b4..0000000 --- a/.mock/definition/__package__.yml +++ /dev/null @@ -1,4311 +0,0 @@ -errors: - UnauthorizedError: - status-code: 401 - type: Error - docs: >- - Provided access token is invalid or does not have access to requested - resource - examples: - - value: - code: not_authorized - message: Request not authorized - ForbiddenError: - status-code: 403 - type: unknown - docs: Provided access token is valid, but is missing the required scopes. - examples: - - value: - code: missing_scopes - message: >- - OAuthForbidden: You are missing the following scopes - - components:write - - value: - key: value - - value: - code: forbidden - message: User is not authorized to perform this action - BadRequestError: - status-code: 400 - type: unknown - docs: Request body was incorrectly formatted. - examples: - - value: - code: bad_request - message: 'Bad Request: Request is malformed' - - value: - key: value - - value: - code: validation_error - message: 'Validation Error: Provided ID is invalid' - NotFoundError: - status-code: 404 - type: Error - docs: Requested resource not found - examples: - - value: - code: resource_not_found - message: 'Requested resource not found: The site cannot be found' - TooManyRequestsError: - status-code: 429 - type: Error - docs: >- - The rate limit of the provided access_token has been reached. Please have - your application respect the X-RateLimit-Remaining header we include on - API responses. - examples: - - value: - code: too_many_requests - message: Too many requests - InternalServerError: - status-code: 500 - type: Error - docs: We had a problem with our server. Try again later. - examples: - - value: - code: internal_error - message: An Internal Error occurred - ConflictError: - status-code: 409 - type: unknown - docs: Collection already exists - examples: - - value: - code: duplicate_collection - message: Collection already exists - - value: - message: '''Site is published to multiple domains at different times' - - value: - code: conflict - message: >- - Conflict: Conflict with server data: Live PATCH updates can't be - applied to items that have never been published - - value: - code: custom_code_max_registered_scripts - message: The maximum number of registered scripts has been reached. - - value: - code: forms_require_republish - message: To access this feature, the site needs to be republished. - - value: - code: ecommerce_not_enabled - message: Ecommerce is not yet initialized -types: - ForbiddenErrorBody: - discriminated: false - union: - - InvalidScopes - - NotEnterprisePlanSite - source: - openapi: ../../../openapi/referenced-specs/v2.yml - BadRequestErrorBody: - discriminated: false - union: - - InvalidDomain - - NoDomains - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ItemsListItemsRequestLastPublished: - properties: - lte: - type: optional - docs: Filter items last published before this date - gte: - type: optional - docs: Filter items last published after this date - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ItemsListItemsLiveRequestLastPublished: - properties: - lte: - type: optional - docs: Filter items last published before this date - gte: - type: optional - docs: Filter items last published after this date - source: - openapi: ../../../openapi/referenced-specs/v2.yml - AuthorizedUser: - properties: - id: - type: optional - docs: The unique ID of the user - email: - type: optional - docs: The user's email address - validation: - format: email - firstName: - type: optional - docs: The user's first name - lastName: - type: optional - docs: The user's last name - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ErrorCode: - enum: - - bad_request - - collection_not_found - - conflict - - duplicate_collection - - duplicate_user_email - - ecommerce_not_enabled - - forbidden - - forms_require_republish - - incompatible_webhook_filter - - internal_error - - invalid_auth_version - - invalid_credentials - - invalid_domain - - invalid_user_email - - item_not_found - - missing_scopes - - no_domains - - not_authorized - - not_enterprise_plan_site - - not_enterprise_plan_workspace - - order_not_found - - resource_not_found - - too_many_requests - - unsupported_version - - unsupported_webhook_trigger_type - - user_limit_reached - - user_not_found - - users_not_enabled - - validation_error - docs: Error code - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Error: - properties: - code: - type: optional - docs: Error code - message: - type: optional - docs: Error message - externalReference: - type: optional - docs: Link to more information - details: - type: optional> - docs: Array of errors - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Application: - properties: - id: - type: optional - docs: Unique identifier for the Application - description: - type: optional - docs: Application description provided by the developer - homepage: - type: optional - docs: Application homepage URL provided by the developer - validation: - format: uri - displayName: - type: optional - docs: Application name provided by the developer - source: - openapi: ../../../openapi/referenced-specs/v2.yml - AuthorizationAuthorizationAuthorizedTo: - properties: - siteIds: - type: optional> - docs: Array of Sites this app is authorized to - workspaceIds: - type: optional> - docs: Array of Workspaces this app is authorized to - userIds: - type: optional> - docs: Array of Users this app is authorized to - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - AuthorizationAuthorization: - docs: The Authorization object - properties: - id: - type: optional - docs: The unique ID of the Authorization instance - createdOn: - type: optional - docs: The date the Authorization was created - lastUsed: - type: optional - docs: The date the Authorization was last used - grantType: - type: optional - docs: The grant type of the Authorization - rateLimit: - type: optional - docs: The default rate limit for the Authorization (requests/min) - scope: - type: optional - docs: Comma separted list of OAuth scopes corresponding to the Authorization - authorizedTo: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Authorization: - properties: - authorization: - type: optional - docs: The Authorization object - application: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Domain: - properties: - id: - type: string - docs: Unique identifier for the Domain - url: - type: optional - docs: The registered Domain name - lastPublished: - type: optional - docs: The date the custom domain was last published to - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Locale: - properties: - id: - type: optional - docs: The unique identifier for the locale. - cmsLocaleId: - type: optional - docs: A CMS-specific identifier for the locale. - enabled: - type: optional - docs: Indicates if the locale is enabled. - displayName: - type: optional - docs: The display name of the locale, typically in English. - displayImageId: - type: optional - docs: An optional ID for an image associated with the locale, nullable. - redirect: - type: optional - docs: Determines if requests should redirect to the locale's subdirectory. - subdirectory: - type: optional - docs: The subdirectory path for the locale, used in URLs. - tag: - type: optional - docs: >- - A tag or code representing the locale, often following a standard - format like 'en-US'. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Locales: - properties: - primary: - type: optional - docs: The primary locale for the site or application. - secondary: - type: optional> - docs: A list of secondary locales available for the site or application. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SiteDataCollectionType: - enum: - - always - - optOut - - disabled - docs: The type of data collection enabled for the site. - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Site: - properties: - id: - type: string - docs: Unique identifier for the Site - workspaceId: - type: optional - docs: Unique identifier for the Workspace - createdOn: - type: optional - docs: Date the Site was created - displayName: - type: optional - docs: Name given to Site - shortName: - type: optional - docs: Slugified version of name - lastPublished: - type: optional - docs: Date the Site was last published - lastUpdated: - type: optional - docs: Date the Site was last updated - previewUrl: - type: optional - docs: URL of a generated image for the given Site - validation: - format: uri - timeZone: - type: optional - docs: Site timezone set under Site Settings - parentFolderId: - type: optional - docs: The ID of the parent folder the Site exists in - customDomains: optional> - locales: optional - dataCollectionEnabled: - type: optional - docs: Indicates if data collection is enabled for the site. - dataCollectionType: - type: optional - docs: The type of data collection enabled for the site. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - InvalidScopes: unknown - NotEnterprisePlanWorkspace: unknown - WorkspaceAuditLogItemPayloadUserAccessMethod: - enum: - - dashboard - - sso - - api - - google - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - User access: - properties: - method: optional - location: - type: optional - docs: The geolocation based on the logged IP address - ipAddress: - type: optional - docs: The captured IP address of the user - source: - openapi: ../../../openapi/referenced-specs/v2.yml - UserAccessAuditLogItemEventSubType: - enum: - - login - - logout - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - UserAccessAuditLogItem: - properties: - eventSubType: optional - payload: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Custom role: - properties: - roleName: - type: optional - docs: The name of the custom role - previousRoleName: - type: optional - docs: The previous name of the custom role - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CustomRoleAuditLogItemEventSubType: - enum: - - role_created - - role_updated - - role_deleted - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CustomRoleAuditLogItem: - properties: - eventSubType: optional - payload: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser: - properties: - id: optional - email: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod: - enum: - - sso - - dashboard - - admin - - access_request - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType: - enum: - - member - - guest - - reviewer - - client - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Workspace membership: - properties: - targetUser: optional - method: optional - userType: optional - roleName: - type: optional - docs: The name of the role that was assigned to the user - previousRoleName: - type: optional - docs: The previous role that the user had - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceMembershipAuditLogItemEventSubType: - enum: - - user_added - - user_removed - - user_role_updated - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceMembershipAuditLogItem: - properties: - eventSubType: optional - payload: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceAuditLogItemPayloadSiteMembershipSite: - properties: - id: optional - slug: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - WorkspaceAuditLogItemPayloadSiteMembershipTargetUser: - properties: - id: optional - email: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - WorkspaceAuditLogItemPayloadSiteMembershipMethod: - enum: - - sso - - invite - - scim - - dashboard - - admin - - access_request - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceAuditLogItemPayloadSiteMembershipUserType: - enum: - - member - - guest - - reviewer - - client - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess: - properties: - id: optional - name: optional - type: optional> - restricted: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Site membership: - properties: - site: optional - targetUser: optional - method: optional - userType: optional - roleName: - type: optional - docs: The name of the role that was assigned to the user - previousRoleName: - type: optional - docs: The previous role that the user had - granularAccess: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SiteMembershipAuditLogItemEventSubType: - enum: - - user_added - - user_removed - - user_role_updated - - user_granular_access_updated - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SiteMembershipAuditLogItem: - properties: - eventSubType: optional - payload: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser: - properties: - id: optional - email: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod: - enum: - - sso - - dashboard - - admin - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType: - enum: - - member - - guest - - reviewer - - client - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem: - properties: - id: optional - email: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Workspace invitation: - properties: - targetUser: optional - method: optional - userType: optional - roleName: - type: optional - docs: The name of the role that was assigned to the user - previousRoleName: - type: optional - docs: The previous role that the user had - targetUsers: >- - optional> - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceInvitationAuditLogItemEventSubType: - enum: - - invite_sent - - invite_accepted - - invite_updated - - invite_canceled - - invite_declined - - access_request_accepted - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceInvitationAuditLogItem: - properties: - eventSubType: optional - payload: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceAuditLogItemPayloadSettingChangeMethod: - enum: - - dashboard - - admin - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Setting change: - properties: - setting: optional> - previousValue: optional - value: optional - method: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SettingChangeAuditLogItem: - properties: - eventSubType: optional> - payload: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceAuditLogItemActor: - properties: - id: optional - email: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - WorkspaceAuditLogItemWorkspace: - properties: - id: optional - slug: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - WorkspaceAuditLogItem: - discriminant: eventType - base-properties: - timestamp: optional - actor: optional - workspace: optional - union: - user_access: - type: UserAccessAuditLogItem - custom_role: - type: CustomRoleAuditLogItem - workspace_membership: - type: WorkspaceMembershipAuditLogItem - site_membership: - type: SiteMembershipAuditLogItem - workspace_invitation: - type: WorkspaceInvitationAuditLogItem - workspace_setting: - type: SettingChangeAuditLogItem - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Pagination: - docs: Pagination object - properties: - limit: - type: optional - docs: The limit used for pagination - access: read-only - offset: - type: optional - docs: The offset used for pagination - access: read-only - total: - type: optional - docs: The total number of records - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WorkspaceAuditLogResponse: - properties: - items: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Sites: - properties: - sites: optional> - source: - openapi: ../../../openapi/referenced-specs/v2.yml - NotEnterprisePlanSite: unknown - Domains: - properties: - customDomains: optional> - source: - openapi: ../../../openapi/referenced-specs/v2.yml - InvalidDomain: unknown - NoDomains: unknown - Redirect: - docs: A single redirection rule, specifying a source URL and a destination URL. - properties: - id: - type: optional - docs: The ID of the specific redirect rule - access: read-only - fromUrl: - type: optional - docs: The source URL path that will be redirected. - toUrl: - type: optional - docs: The target URL path where the user or client will be redirected. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Redirects: - docs: Site redirects response - properties: - redirects: - type: optional> - docs: List of redirects for a given site - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SitePlanId: - enum: - - value: hosting-basic-v3 - name: HostingBasicV3 - - value: hosting-cms-v3 - name: HostingCmsV3 - - value: hosting-business-v3 - name: HostingBusinessV3 - - value: hosting-ecommerce-standard-v2 - name: HostingEcommerceStandardV2 - - value: hosting-ecommerce-plus-v2 - name: HostingEcommercePlusV2 - - value: hosting-ecommerce-advanced-v2 - name: HostingEcommerceAdvancedV2 - - value: hosting-basic-v4 - name: HostingBasicV4 - - value: hosting-cms-v4 - name: HostingCmsV4 - - value: hosting-business-v4 - name: HostingBusinessV4 - - value: hosting-ecommerce-standard-v3 - name: HostingEcommerceStandardV3 - - value: hosting-ecommerce-plus-v3 - name: HostingEcommercePlusV3 - - value: hosting-ecommerce-advanced-v3 - name: HostingEcommerceAdvancedV3 - docs: ID of the hosting plan. - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SitePlanName: - enum: - - value: Basic Hosting - name: BasicHosting - - value: CMS Hosting - name: CmsHosting - - value: Business Hosting - name: BusinessHosting - - value: ECommerce Standard Hosting - name: ECommerceStandardHosting - - value: ECommerce Plus Hosting - name: ECommercePlusHosting - - value: ECommerce Advanced Hosting - name: ECommerceAdvancedHosting - docs: Name of the hosting plan. - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SitePlan: - properties: - id: - type: optional - docs: ID of the hosting plan. - name: - type: optional - docs: Name of the hosting plan. - pricingInfo: - type: optional - docs: URL for more information about Webflow hosting plan pricing. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - RobotsRulesItem: - properties: - userAgent: - type: string - docs: The user agent the rules apply to. - allows: - type: optional> - docs: List of paths allowed for this user agent. - disallows: - type: optional> - docs: List of paths disallowed for this user agent. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Robots: - docs: The robots.txt file for a given site - properties: - rules: - type: optional> - docs: List of rules for user agents. - sitemap: - type: optional - docs: URL to the sitemap. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SiteActivityLogItemEvent: - enum: - - styles_modified - - site_published - - ix2_modified_on_page - - page_dom_modified - - cms_item - - backup_created - - page_custom_code_modified - - symbols_modified - - variable_modified - - variables_modified - - cms_collection - - page_settings_modified - - page_settings_custom_code_modified - - ix2_modified_on_component - - ix2_modified_on_class - - site_custom_code_modified - - page_duplicated - - secondary_locale_page_content_modified - - page_renamed - - page_created - - page_deleted - - site_unpublished - - backup_restored - - locale_added - - branch_created - - locale_display_name_updated - - locale_subdirectory_updated - - branch_merged - - locale_tag_updated - - branch_deleted - - locale_enabled - - locale_removed - - locale_disabled - - library_shared - - library_unshared - - library_installed - - library_uninstalled - - library_update_shared - - library_update_accepted - - branch_review_created - - branch_review_approved - - branch_review_canceled - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SiteActivityLogItemResourceOperation: - enum: - - CREATED - - MODIFIED - - PUBLISHED - - UNPUBLISHED - - DELETED - - GROUP_REORDERED - - GROUP_CREATED - - GROUP_DELETED - - REORDERED - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SiteActivityLogItemUser: - properties: - id: optional - displayName: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - SiteActivityLogItem: - properties: - id: optional - createdOn: optional - lastUpdated: optional - event: optional - resourceOperation: optional - user: optional - resourceId: optional - resourceName: optional - newValue: optional - previousValue: optional - payload: optional> - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SiteActivityLogResponse: - properties: - items: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionListArrayItem: - docs: A collection object - properties: - id: - type: string - docs: Unique identifier for a Collection - displayName: - type: optional - docs: Name given to the Collection - singularName: - type: optional - docs: >- - The name of one Item in Collection (e.g. ”Blog Post” if the Collection - is called “Blog Posts”) - slug: - type: optional - docs: Slug of Collection in Site URL structure - createdOn: - type: optional - docs: The date the collection was created - access: read-only - lastUpdated: - type: optional - docs: The date the collection was last updated - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionList: - properties: - collections: - type: optional> - docs: An array of Collections - source: - openapi: ../../../openapi/referenced-specs/v2.yml - StaticFieldType: - enum: - - Color - - DateTime - - Email - - File - - Image - - Link - - MultiImage - - Number - - Phone - - PlainText - - RichText - - Switch - - VideoLink - docs: Choose these appropriate field type for your collection data - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Static Field: - properties: - id: - type: optional - docs: Unique identifier for a Field - access: read-only - isEditable: - type: optional - docs: Define whether the field is editable - access: read-only - isRequired: - type: optional - docs: define whether a field is required in a collection - type: - type: StaticFieldType - docs: Choose these appropriate field type for your collection data - displayName: - type: string - docs: The name of a field - helpText: - type: optional - docs: Additional text to help anyone filling out this field - source: - openapi: ../../../openapi/referenced-specs/v2.yml - MetadataOptionsItem: - docs: A single option value for the Option field. - properties: - name: - type: string - docs: The name of the option - id: - type: optional - docs: The unique identifier of the option - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Metadata: - docs: The metadata for the Option field. - properties: - options: - docs: The option values for the Option field. - type: list - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Option Field: - properties: - id: - type: optional - docs: Unique identifier for a Field - access: read-only - isEditable: - type: optional - docs: Define whether the field is editable - access: read-only - isRequired: - type: optional - docs: define whether a field is required in a collection - type: - type: literal<"Option"> - docs: >- - The [Option field - type](/data/reference/field-types-item-values#option) - displayName: - type: string - docs: The name of a field - helpText: - type: optional - docs: Additional text to help anyone filling out this field - metadata: Metadata - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ReferenceFieldType: - enum: - - MultiReference - - Reference - docs: Choose these appropriate field type for your collection data - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ReferenceFieldMetadata: - docs: >- - The collectionId for the referenced collection. Only applicable for - Reference and MultiReference fields. - properties: - collectionId: - type: string - docs: The unique identifier of the collection - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Reference Field: - properties: - id: - type: optional - docs: Unique identifier for a Field - access: read-only - isEditable: - type: optional - docs: Define whether the field is editable - access: read-only - isRequired: - type: optional - docs: define whether a field is required in a collection - type: - type: ReferenceFieldType - docs: Choose these appropriate field type for your collection data - displayName: - type: string - docs: The name of a field - helpText: - type: optional - docs: Additional text to help anyone filling out this field - metadata: - type: ReferenceFieldMetadata - docs: >- - The collectionId for the referenced collection. Only applicable for - Reference and MultiReference fields. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - FieldCreate: - discriminated: false - docs: Details about the field of a collection - union: - - type: Static Field - - type: Option Field - - type: Reference Field - source: - openapi: ../../../openapi/referenced-specs/v2.yml - FieldType: - enum: - - Color - - DateTime - - Email - - ExtFileRef - - File - - Image - - Link - - MultiImage - - MultiReference - - Number - - Option - - Phone - - PlainText - - Reference - - RichText - - Switch - - VideoLink - docs: Choose these appropriate field type for your collection data - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - FieldValidationsAdditionalPropertiesAdditionalProperties: - properties: - additionalProperties: unknown - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - FieldValidationsAdditionalProperties: - discriminated: false - union: - - string - - double - - boolean - - integer - - FieldValidationsAdditionalPropertiesAdditionalProperties - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - FieldValidations: - docs: The validations for the field - properties: - additionalProperties: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Field: - docs: The details of a field in a collection - properties: - id: - type: string - docs: Unique identifier for a Field - isRequired: - type: boolean - docs: define whether a field is required in a collection - isEditable: - type: optional - docs: Define whether the field is editable - access: read-only - type: - type: FieldType - docs: Choose these appropriate field type for your collection data - slug: - type: optional - docs: >- - Slug of Field in Site URL structure. Slugs should be all lowercase - with no spaces. Any spaces will be converted to "-." - displayName: - type: string - docs: The name of a field - helpText: - type: optional - docs: Additional text to help anyone filling out this field - validations: - type: optional - docs: The validations for the field - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Collection: - docs: A collection object - properties: - id: - type: string - docs: Unique identifier for a Collection - displayName: - type: string - docs: Name given to the Collection - singularName: - type: string - docs: >- - The name of one Item in Collection (e.g. ”Blog Post” if the Collection - is called “Blog Posts”) - slug: - type: optional - docs: Slug of Collection in Site URL structure - createdOn: - type: optional - docs: The date the collection was created - access: read-only - lastUpdated: - type: optional - docs: The date the collection was last updated - access: read-only - fields: - docs: The list of fields in the Collection - type: list - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemFieldData: - properties: - name: - type: string - docs: Name of the Item - slug: - type: string - docs: >- - URL structure of the Item in your site. Note: Updates to an item slug - will break all links referencing the old slug. - extra-properties: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CollectionItem: - docs: > - A Collection Item represents a single entry in your collection. Each item - includes: - - - - **System metadata** - Automatically managed fields like IDs and - timestamp
- - - **Status flags** - Controls for managing content state: `isDraft`, - `isArchived `
- - - **Content fields** - Stored in `fieldData`. Each item needs a `name` and - `slug`, and may include additional fields matching your collection's - schema definition. - properties: - id: - type: optional - docs: Unique identifier for the Item - access: read-only - cmsLocaleId: - type: optional - docs: Identifier for the locale of the CMS item - lastPublished: - type: optional - docs: The date the item was last published - access: read-only - lastUpdated: - type: optional - docs: The date the item was last updated - access: read-only - createdOn: - type: optional - docs: The date the item was created - access: read-only - isArchived: - type: optional - docs: Boolean determining if the Item is set to archived - default: false - isDraft: - type: optional - docs: Boolean determining if the Item is set to draft - default: false - fieldData: CollectionItemFieldData - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemListPagination: - properties: - limit: - type: optional - docs: The limit specified in the request - default: 100 - offset: - type: optional - docs: The offset specified for pagination - default: 0 - total: - type: optional - docs: Total number of items in the collection - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CollectionItemList: - docs: Results from collection items list - properties: - items: - type: optional> - docs: List of Items within the collection - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemPostSingleFieldData: - properties: - name: - type: string - docs: Name of the Item - slug: - type: string - docs: >- - URL structure of the Item in your site. Note: Updates to an item slug - will break all links referencing the old slug. - extra-properties: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CollectionItemPostSingle: - docs: > - A Collection Item represents a single entry in your collection. Each item - includes: - - - - **System metadata** - Automatically managed fields like IDs and - timestamp
- - - **Status flags** - Controls for managing content state: `isDraft`, - `isArchived `
- - - **Content fields** - Stored in `fieldData`. Each item needs a `name` and - `slug`, and may include additional fields matching your collection's - schema definition. - properties: - id: - type: optional - docs: Unique identifier for the Item - access: read-only - cmsLocaleId: - type: optional - docs: Identifier for the locale of the CMS item - lastPublished: - type: optional - docs: The date the item was last published - access: read-only - lastUpdated: - type: optional - docs: The date the item was last updated - access: read-only - createdOn: - type: optional - docs: The date the item was created - access: read-only - isArchived: - type: optional - docs: Boolean determining if the Item is in an archived state. - default: false - isDraft: - type: optional - docs: Boolean determining if the Item is in a draft state. - default: true - fieldData: CollectionItemPostSingleFieldData - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemWithIdInputFieldData: - properties: - name: - type: optional - docs: Name of the Item - slug: - type: optional - docs: >- - URL structure of the Item in your site. Note: Updates to an item slug - will break all links referencing the old slug. - extra-properties: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CollectionItemWithIdInput: - docs: > - The fields that define the schema for a given Item are based on the - Collection that Item belongs to. Beyond the user defined fields, there are - a handful of additional fields that are automatically created for all - items - properties: - id: - type: string - docs: Unique identifier for the Item - cmsLocaleId: - type: optional - docs: Identifier for the locale of the CMS item - lastPublished: - type: optional - docs: The date the item was last published - access: read-only - lastUpdated: - type: optional - docs: The date the item was last updated - access: read-only - createdOn: - type: optional - docs: The date the item was created - access: read-only - isArchived: - type: optional - docs: Boolean determining if the Item is set to archived - isDraft: - type: optional - docs: Boolean determining if the Item is set to draft - fieldData: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemListNoPagination: - docs: Results from collection items list - properties: - items: - type: optional> - docs: List of Items within the collection - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Conflict: unknown - BulkCollectionItemFieldData: - properties: - name: - type: optional - docs: Name of the Item - slug: - type: optional - docs: >- - URL structure of the Item in your site. Note: Updates to an item slug - will break all links referencing the old slug. - extra-properties: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - BulkCollectionItem: - docs: > - The fields that define the schema for a given Item are based on the - Collection that Item belongs to. Beyond the user defined fields, there are - a handful of additional fields that are automatically created for all - items - properties: - id: - type: optional - docs: Unique identifier for the Item - cmsLocaleIds: - type: optional> - docs: Array of identifiers for the locales where the item will be created - lastPublished: - type: optional - docs: The date the item was last published - access: read-only - lastUpdated: - type: optional - docs: The date the item was last updated - access: read-only - createdOn: - type: optional - docs: The date the item was created - access: read-only - isArchived: - type: optional - docs: Boolean determining if the Item is set to archived - default: false - isDraft: - type: optional - docs: Boolean determining if the Item is set to draft - default: false - fieldData: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemPatchSingleFieldData: - properties: - name: - type: optional - docs: Name of the Item - slug: - type: optional - docs: >- - URL structure of the Item in your site. Note: Updates to an item slug - will break all links referencing the old slug. - extra-properties: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CollectionItemPatchSingle: - docs: > - The fields that define the schema for a given Item are based on the - Collection that Item belongs to. Beyond the user defined fields, there are - a handful of additional fields that are automatically created for all - items - properties: - id: - type: optional - docs: Unique identifier for the Item - access: read-only - cmsLocaleId: - type: optional - docs: Identifier for the locale of the CMS item - lastPublished: - type: optional - docs: The date the item was last published - access: read-only - lastUpdated: - type: optional - docs: The date the item was last updated - access: read-only - createdOn: - type: optional - docs: The date the item was created - access: read-only - isArchived: - type: optional - docs: Boolean determining if the Item is set to archived - isDraft: - type: optional - docs: Boolean determining if the Item is set to draft - fieldData: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CommentThreadAuthor: - properties: - userId: - type: string - docs: The unique identifier of the author - email: - type: string - docs: Email of the author - name: - type: string - docs: Name of the author - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CommentThreadMentionedUsersItem: - properties: - userId: - type: string - docs: The unique identifier of the mentioned user - email: - type: string - docs: Email of the user - name: - type: string - docs: Name of the User - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CommentThread: - docs: > - A comment thread represents a conversation between users on a specific - page. Each comment thread has a unique identifier and can contain multiple - comments. Retrieve comment replies using the replies API endpoint. - properties: - id: - type: string - docs: Unique identifier for the comment thread - siteId: - type: string - docs: The site unique identifier - pageId: - type: string - docs: The page unique identifier - localeId: - type: optional - docs: The locale unique identifier - access: read-only - itemId: - type: optional - docs: The item unique identifier - access: read-only - breakpoint: - type: string - docs: The breakpoint the comment was left on - url: - type: string - docs: The URL of the page the comment was left on - content: - type: string - docs: The content of the comment reply - isResolved: - type: boolean - docs: Boolean determining if the comment thread is resolved - default: false - author: CommentThreadAuthor - mentionedUsers: - docs: >- - List of mentioned users. This is an empty array until email - notifications are sent, which can take up to 5 minutes after the - comment is created. - type: list - createdOn: - type: string - docs: The date the item was created - lastUpdated: - type: string - docs: The date the item was last updated - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CommentThreadListPagination: - properties: - limit: - type: integer - docs: The limit specified in the request (default 100) - default: 100 - offset: - type: integer - docs: The offset specified for pagination - default: 0 - total: - type: integer - docs: Total number of comment threads - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CommentThreadList: - docs: > - A list of comment threads on the site. Contains the content of the first - reply. - properties: - comments: list - pagination: CommentThreadListPagination - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CommentReplyAuthor: - properties: - id: - type: string - docs: The unique identifier of the author - email: - type: string - docs: Email of the author - name: - type: string - docs: Name of the author - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CommentReplyMentionedUsersItem: - properties: - id: - type: string - docs: The unique identifier of the mentioned user - email: - type: string - docs: Email of the user - name: - type: string - docs: Name of the User - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CommentReply: - docs: > - A comment thread represents a conversation between users on a specific - page. Each comment thread has a unique identifier and can contain multiple - comments. - properties: - id: - type: string - docs: Unique identifier for the comment thread - commentId: - type: string - docs: The comment reply unique identifier - siteId: - type: string - docs: The site unique identifier - pageId: - type: string - docs: The page unique identifier - localeId: - type: optional - docs: The locale unique identifier - access: read-only - breakpoint: - type: string - docs: The breakpoint the comment was left on - content: - type: string - docs: The content of the comment reply - isResolved: - type: boolean - docs: Boolean determining if the comment thread is resolved - default: false - author: CommentReplyAuthor - mentionedUsers: - type: optional> - docs: >- - List of mentioned users is an empty array until email notifications - are sent. - lastUpdated: - type: optional - docs: The date the item was last updated - access: read-only - createdOn: - type: optional - docs: The date the item was created - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CommentReplyListPagination: - properties: - limit: - type: integer - docs: The limit specified in the request (default 100) - default: 100 - offset: - type: integer - docs: The offset specified for pagination - default: 0 - total: - type: integer - docs: Total number of comment replies - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CommentReplyList: - docs: | - A list of comment replies. - properties: - comments: list - pagination: CommentReplyListPagination - source: - openapi: ../../../openapi/referenced-specs/v2.yml - PageSeo: - docs: SEO-related fields for the Page - properties: - title: - type: optional - docs: The Page title shown in search engine results - description: - type: optional - docs: The Page description shown in search engine results - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - PageOpenGraph: - docs: Open Graph fields for the Page - properties: - title: - type: optional - docs: The title supplied to Open Graph annotations - titleCopied: - type: optional - docs: Indicates the Open Graph title was copied from the SEO title - default: true - access: read-only - description: - type: optional - docs: The description supplied to Open Graph annotations - descriptionCopied: - type: optional - docs: >- - Indicates the Open Graph description was copied from the SEO - description - default: true - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Page: - docs: The Page object - properties: - id: - type: string - docs: Unique identifier for the Page - siteId: - type: optional - docs: Unique identifier for the Site - access: read-only - title: - type: optional - docs: Title of the Page - slug: - type: optional - docs: slug of the Page (derived from title) - parentId: - type: optional - docs: Identifier of the parent folder - access: read-only - collectionId: - type: optional - docs: >- - Unique identifier for a linked Collection, value will be null if the - Page is not part of a Collection. - access: read-only - createdOn: - type: optional - docs: The date the Page was created - access: read-only - lastUpdated: - type: optional - docs: The date the Page was most recently updated - access: read-only - archived: - type: optional - docs: Whether the Page has been archived - default: false - access: read-only - draft: - type: optional - docs: Whether the Page is a draft - default: false - access: read-only - canBranch: - type: optional - docs: >- - Indicates whether the Page supports [Page - Branching](https://university.webflow.com/lesson/page-branching). - Pages that are already branches cannot be branched again. - default: false - access: read-only - isBranch: - type: optional - docs: >- - Indicates whether the Page is a Branch of another Page [Page - Branching](https://university.webflow.com/lesson/page-branching) - default: false - access: read-only - branchId: - type: optional - docs: If the Page is a Branch of another Page, this is the ID of the Branch - seo: - type: optional - docs: SEO-related fields for the Page - openGraph: - type: optional - docs: Open Graph fields for the Page - localeId: - type: optional - docs: Unique ID of the page locale - access: read-only - publishedPath: - type: optional - docs: Relative path of the published page URL - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - PageList: - docs: The Page object - properties: - pages: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - TextNodeText: - docs: The text content of the node - properties: - html: - type: optional - docs: The HTML content of the text node. - text: - type: optional - docs: The raw text content of the text node. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - TextNode: - docs: > - Represents text content within the DOM. It contains both the raw text and - its HTML representation. Additional attributes can be associated with the - text for styling or other purposes. - properties: - id: - type: string - docs: Node UUID - text: - type: TextNodeText - docs: The text content of the node - attributes: - type: optional> - docs: The custom attributes of the node - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ImageNodeImage: - docs: The image details of the node - properties: - alt: optional - assetId: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - ImageNode: - docs: > - Represents an image within the DOM. It contains details about the image, - such as its alternative text (alt) for accessibility and an asset - identifier for fetching the actual image resource. Additional attributes - can be associated with the image for styling or other purposes. - properties: - id: - type: string - docs: Node UUID - image: - type: ImageNodeImage - docs: The image details of the node - attributes: - type: optional> - docs: The custom attributes of the node - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Text: - docs: The text content of the node - properties: - html: - type: optional - docs: The HTML content of the text node. - text: - type: optional - docs: The raw text content of the text node. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ComponentPropertyType: - enum: - - value: Plain Text - name: PlainText - - value: Rich Text - name: RichText - - value: Alt Text - name: AltText - docs: The type of the property. - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ComponentProperty: - docs: > - Represents a property of a component instance in the DOM. A property - contains a list of both the raw text and the HTML representation, allowing - for flexibility in rendering and processing. Additional attributes can be - associated with the text for styling or other purposes. - properties: - propertyId: - type: optional - docs: The ID of the property. - type: - type: optional - docs: The type of the property. - label: - type: optional - docs: The label of the property in the UI. - text: - type: optional - docs: >- - Represents text content within the DOM. It contains both the raw text - and its HTML representation. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ComponentNode: - docs: > - Represents a component instance within the DOM. It contains details about - the component instance, such as its type and properties. - properties: - id: - type: string - docs: The unique identifier of the component instance node - componentId: - type: string - docs: The unique identifier of the component - propertyOverrides: - docs: List of component properties with overrides for a component instance. - type: list - source: - openapi: ../../../openapi/referenced-specs/v2.yml - TextInputNode: - docs: > - Represents text input and textarea elements within the DOM. It contains - the placeholder text in the input. Additional attributes can be associated - with the text for styling or other purposes. - properties: - id: - type: string - docs: Node UUID - placeholder: - type: string - docs: The placeholder text of the input node - attributes: - type: optional> - docs: The custom attributes of the node - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SelectNodeChoicesItem: - properties: - value: - type: string - docs: The value of the choice when selected. - text: - type: string - docs: The text to display for the choice. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - SelectNode: - docs: > - Represents select elements within the DOM. It contains the list of choices - in the select. Additional attributes can be associated with the text for - styling or other purposes. - properties: - id: - type: string - docs: Node UUID - choices: - docs: The list of choices in this select node. - type: list - attributes: - type: optional> - docs: The custom attributes of the node - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SubmitButtonNode: - docs: > - Represents submit button elements within the DOM. It contains the text and - waiting text of the button. Additional attributes can be associated with - the text for styling or other purposes. - properties: - id: - type: string - docs: Node UUID - value: - type: string - docs: The text content of the submit button. - waitingText: - type: string - docs: The text to show while the form is submitting. - attributes: - type: optional> - docs: The custom attributes of the node - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SearchButtonNode: - docs: > - Represents search button elements within the DOM. It contains the text of - the button. Additional attributes can be associated with the text for - styling or other purposes. - properties: - id: - type: string - docs: Node UUID - value: - type: string - docs: The text content of the search button. - attributes: - type: optional> - docs: The custom attributes of the node - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Node: - discriminant: type - base-properties: {} - docs: > - A generic representation of a content element within the Document Object - Model (DOM). Each node has a unique identifier and a specific type that - determines its content structure and attributes. - union: - text: - type: TextNode - image: - type: ImageNode - component-instance: - type: ComponentNode - text-input: - type: TextInputNode - select: - type: SelectNode - submit-button: - type: SubmitButtonNode - search-button: - type: SearchButtonNode - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Dom: - docs: > - The DOM (Document Object Model) schema represents the content structure of - a web page or component. It captures various content nodes along with - their associated attributes. Each node has a unique identifier and can be - of different types like text, image or component-instance. The schema also - provides pagination details for scenarios where the content nodes are too - many to be fetched in a single request. - properties: - pageId: - type: optional - docs: Page ID - branchId: - type: optional - docs: >- - The unique identifier of a [specific page - branch.](https://help.webflow.com/hc/en-us/articles/33961355506195-Page-branching) - nodes: optional> - pagination: optional - lastUpdated: - type: optional - docs: The date the page dom was most recently updated - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - TextNodeWrite: - docs: Update a text node - properties: - nodeId: - type: string - docs: Node UUID - text: - type: string - docs: >- - HTML content of the node, including the HTML tag. The HTML tags must - be the same as what's returned from the Get Content endpoint. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem: - properties: - propertyId: - type: string - docs: The ID of the property. - text: - type: string - docs: > - The new string or HTML value used to override the component instance - property value. - - The provided value must be compatible with the type of the component - instance property. - - For example, attempting to override a single-line plain-text property - with a multi-line - - value will result in an error. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - ComponentInstanceNodePropertyOverridesWrite: - docs: Update text property overrides of a component instance - properties: - nodeId: - type: string - docs: Node UUID - propertyOverrides: - docs: >- - A list of component instance properties to override within the - specified secondary locale. - type: list - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SelectNodeWriteChoicesItem: - properties: - value: - type: string - docs: The value of the choice when selected. - text: - type: string - docs: The text to display for the choice. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Select: - docs: Update choices on a select node - properties: - nodeId: - type: string - docs: Node UUID - choices: - docs: The list of choices to set on the select node. - type: list - source: - openapi: ../../../openapi/referenced-specs/v2.yml - TextInputNodeWrite: - docs: Update placeholder text on a text input node - properties: - nodeId: - type: string - docs: Node UUID - placeholder: - type: string - docs: The placeholder text of the input node - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SubmitButtonNodeWrite: - docs: Update a submit button node - properties: - nodeId: - type: string - docs: Node UUID - value: - type: optional - docs: The text content of the submit button. - waitingText: - type: optional - docs: The text to show while the form is submitting. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SearchButtonNodeWrite: - docs: Update a search button node - properties: - nodeId: - type: string - docs: Node UUID - value: - type: string - docs: The text content of the search button. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Component: - docs: The Component object - properties: - id: - type: string - docs: Unique identifier for the Component - name: - type: optional - docs: Component Name - access: read-only - group: - type: optional - docs: The group that the component belongs to - access: read-only - description: - type: optional - docs: Component Description - access: read-only - readonly: - type: optional - docs: >- - Indicates whether the component is read-only. Components that cannot - be updated within this Site are set to readonly. Workspace Libraries - are a good example. - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ComponentList: - docs: List of Components on a site. - properties: - components: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ComponentDom: - docs: > - The Component DOM schema represents the content structure of a component. - Similar to Page DOM, it captures various content nodes and their - associated attributes, but specifically for a component's structure. Each - node has a unique identifier and can contain text, images, select or text - inputs, submit buttons, or nested component instances. - properties: - componentId: - type: optional - docs: Component ID - nodes: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ComponentProperties: - docs: > - The Component Properties schema represents a list of properties that store - text content. Each property has a unique identifier and can be of - different types like plain text or rich text. The schema also provides - pagination details for scenarios where there more properties than the - limit. - properties: - componentId: - type: optional - docs: Component ID - access: read-only - properties: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ScriptApplyLocation: - enum: - - header - - footer - docs: >- - Location of the script, either in the header or footer of the published - site - default: header - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ScriptApply: - properties: - id: - type: string - docs: ID of the registered custom code script - location: - type: ScriptApplyLocation - docs: >- - Location of the script, either in the header or footer of the - published site - default: header - version: - type: string - docs: Semantic Version String for the registered script *e.g. 0.0.1* - attributes: - type: optional> - docs: >- - Developer-specified key/value pairs to be applied as attributes to the - script - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ScriptApplyList: - properties: - scripts: - type: optional> - docs: A list of scripts applied to a Site or a Page - lastUpdated: - type: optional - docs: Date when the Site's scripts were last updated - access: read-only - createdOn: - type: optional - docs: Date when the Site's scripts were created - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CustomCodeHostedResponse: - docs: Registered custom code for application - properties: - id: - type: optional - docs: Human readable id, derived from the user-specified display name - access: read-only - canCopy: - type: optional - docs: >- - Define whether the script can be copied on site duplication and - transfer - default: false - displayName: - type: optional - docs: >- - User-facing name for the script. Must be between 1 and 50 alphanumeric - characters - hostedLocation: - type: optional - docs: URI for an externally hosted script location - integrityHash: - type: optional - docs: >- - Sub-Resource Integrity Hash. Only required for externally hosted - scripts (passed via hostedLocation) - createdOn: - type: optional - docs: Timestamp when the script version was created - access: read-only - lastUpdated: - type: optional - docs: Timestamp when the script version was last updated - access: read-only - version: - type: optional - docs: A Semantic Version (SemVer) string, denoting the version of the script - source: - openapi: ../../../openapi/referenced-specs/v2.yml - RegisteredScriptList: - docs: A list of scripts registered to the site - properties: - registeredScripts: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CustomCodeInlineResponse: - docs: Registered custom code for application - properties: - id: - type: optional - docs: Human readable id, derived from the user-specified display name - access: read-only - canCopy: - type: optional - docs: >- - Define whether the script can be copied on site duplication and - transfer - default: false - displayName: - type: optional - docs: >- - User-facing name for the script. Must be between 1 and 50 alphanumeric - characters - hostedLocation: - type: optional - docs: URI for an externally hosted script location - integrityHash: - type: optional - docs: >- - Sub-Resource Integrity Hash. Only required for externally hosted - scripts (passed via hostedLocation) - createdOn: - type: optional - docs: Timestamp when the script version was created - access: read-only - lastUpdated: - type: optional - docs: Timestamp when the script version was last updated - access: read-only - version: - type: optional - docs: A Semantic Version (SemVer) string, denoting the version of the script - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Scripts: - docs: A list of scripts applied to a Site or a Page - type: list - CustomCodeBlockType: - enum: - - page - - site - docs: Whether the Custom Code script is applied at the Site-level or Page-level - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CustomCodeBlock: - docs: A specific instance of Custom Code applied to a Site or Page - properties: - siteId: - type: optional - docs: The Site ID where the custom code was applied - pageId: - type: optional - docs: The Page ID (if applied at Page-level) - type: - type: optional - docs: >- - Whether the Custom Code script is applied at the Site-level or - Page-level - scripts: optional - createdOn: - type: optional - docs: The date the Block was created - access: read-only - lastUpdated: - type: optional - docs: The date the Block was most recently updated - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ListCustomCodeBlocks: - docs: Custom Code Blocks corresponding to where scripts were applied - properties: - blocks: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - AssetVariant: - docs: Asset variant details - properties: - hostedUrl: - type: string - docs: URL of where the asset variant is hosted - validation: - format: uri - originalFileName: - type: string - docs: Original file name of the variant - displayName: - type: string - docs: Display name of the variant - format: - type: string - docs: format of the variant - width: - type: integer - docs: Width in pixels - height: - type: optional - docs: Height in pixels - quality: - type: integer - docs: Value between 0 and 100 representing the image quality - error: - type: optional - docs: Any associated validation errors - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Asset: - docs: Asset details - properties: - id: - type: optional - docs: Unique identifier for this asset - access: read-only - contentType: - type: optional - docs: File format type - access: read-only - size: - type: optional - docs: size in bytes - access: read-only - siteId: - type: optional - docs: Unique identifier for the site that hosts this asset - access: read-only - hostedUrl: - type: optional - docs: Link to the asset - validation: - format: uri - access: read-only - originalFileName: - type: optional - docs: Original file name at the time of upload - access: read-only - displayName: - type: string - docs: Display name of the asset - lastUpdated: - type: optional - docs: Date the asset metadata was last updated - access: read-only - createdOn: - type: optional - docs: Date the asset metadata was created - access: read-only - variants: - docs: >- - A list of [asset - variants](https://help.webflow.com/hc/en-us/articles/33961378697107-Responsive-images) - created by Webflow to serve your site responsively. - type: list - altText: - type: optional - docs: The visual description of the asset - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Assets: - docs: A list of assets - properties: - assets: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - AssetUploadUploadDetails: - docs: Metadata for uploading the asset binary - properties: - acl: optional - bucket: optional - X-Amz-Algorithm: optional - X-Amz-Credential: optional - X-Amz-Date: optional - key: optional - Policy: optional - X-Amz-Signature: optional - success_action_status: optional - content-type: optional - Cache-Control: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - AssetUpload: - properties: - uploadDetails: - type: optional - docs: Metadata for uploading the asset binary - contentType: optional - id: optional - parentFolder: - type: optional - docs: Parent folder for the asset - uploadUrl: - type: optional - validation: - format: uri - assetUrl: - type: optional - docs: S3 link to the asset - validation: - format: uri - hostedUrl: - type: optional - docs: Represents the link to the asset - validation: - format: uri - originalFileName: - type: optional - docs: >- - Original file name when uploaded. If not specified at time of upload, - it may be extracted from the raw file name - createdOn: - type: optional - docs: Date the asset metadata was created - lastUpdated: - type: optional - docs: Date the asset metadata was last updated - source: - openapi: ../../../openapi/referenced-specs/v2.yml - AssetFolder: - docs: Asset Folder details - properties: - id: - type: optional - docs: Unique identifier for the Asset Folder - displayName: - type: optional - docs: User visible name for the Asset Folder - parentFolder: - type: optional - docs: Pointer to parent Asset Folder (or null if root) - assets: - type: optional> - docs: Array of Asset instances in the folder - siteId: - type: optional - docs: The unique ID of the site the Asset Folder belongs to - createdOn: - type: optional - docs: Date that the Asset Folder was created on - lastUpdated: - type: optional - docs: Date that the Asset Folder was last updated on - source: - openapi: ../../../openapi/referenced-specs/v2.yml - AssetFolderList: - docs: The Asset Folders object - properties: - assetFolders: - type: optional> - docs: A list of Asset folders - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - TriggerType: - enum: - - form_submission - - site_publish - - page_created - - page_metadata_updated - - page_deleted - - ecomm_new_order - - ecomm_order_changed - - ecomm_inventory_changed - - collection_item_created - - collection_item_changed - - collection_item_deleted - - collection_item_published - - collection_item_unpublished - - comment_created - docs: > - The type of event that triggered the request. See the the documentation - for details on [supported events](/data/reference/all-events). - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WebhookFilter: - docs: >- - Only supported for the `form_submission` trigger type. Filter for the form - you want Webhooks to be sent for. - properties: - name: - type: optional - docs: The name of the form you'd like to recieve notifications for. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Webhook: - properties: - id: - type: optional - docs: Unique identifier for the Webhook registration - access: read-only - triggerType: optional - url: - type: optional - docs: URL to send the Webhook payload to - workspaceId: - type: optional - docs: Unique identifier for the Workspace the Webhook is registered in - access: read-only - siteId: - type: optional - docs: Unique identifier for the Site the Webhook is registered in - access: read-only - filter: - type: optional - docs: >- - Only supported for the `form_submission` trigger type. Filter for the - form you want Webhooks to be sent for. - lastTriggered: - type: optional - docs: Date the Webhook instance was last triggered - access: read-only - createdOn: - type: optional - docs: Date the Webhook registration was created - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - WebhookList: - properties: - webhooks: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - FormFieldValueType: - enum: - - Plain - - Email - - Password - - Phone - - Number - docs: The field type - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - FormFieldValue: - docs: An object containing field info for a specific fieldID. - properties: - displayName: - type: optional - docs: The field name displayed on the site - type: - type: optional - docs: The field type - placeholder: - type: optional - docs: The placeholder text for the field - userVisible: - type: optional - docs: Whether the field is visible to the user - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - FormField: - type: map - docs: A collection of form fields with additional properties. - FormResponseSettings: - docs: Settings for form responses - properties: - redirectUrl: - type: optional - docs: The url or path to redirect the user to after form submission - redirectMethod: - type: optional - docs: The HTTP request method to use for the redirectUrl (eg. POST or GET) - redirectAction: - type: optional - docs: The action to take after form submission - sendEmailConfirmation: - type: optional - docs: Whether to send an email confirmation to the user - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Form: - docs: A Webflow form - properties: - displayName: - type: optional - docs: The Form name displayed on the site - createdOn: - type: optional - docs: Date that the Form was created on - lastUpdated: - type: optional - docs: Date that the Form was last updated on - fields: - type: optional - docs: A collection of form field objects - responseSettings: - type: optional - docs: Settings for form responses - id: - type: optional - docs: The unique ID for the Form - siteId: - type: optional - docs: The unique ID of the Site the Form belongs to - siteDomainId: - type: optional - docs: The unique ID corresponding to the site's Domain name - pageId: - type: optional - docs: The unique ID for the Page on which the Form is placed - pageName: - type: optional - docs: The user-visible name of the Page where the Form is placed - formElementId: - type: optional - docs: The unique ID of the Form element - workspaceId: - type: optional - docs: The unique ID of the Workspace the Site belongs to - source: - openapi: ../../../openapi/referenced-specs/v2.yml - FormList: - properties: - forms: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - FormSubmission: - properties: - id: - type: optional - docs: The unique ID of the Form submission - displayName: - type: optional - docs: The Form name displayed on the site - siteId: - type: optional - docs: The unique ID of the Site the Form belongs to - workspaceId: - type: optional - docs: The unique ID of the Workspace the Site belongs to - dateSubmitted: - type: optional - docs: Date that the Form was submitted on - formResponse: - type: optional> - docs: The data submitted in the Form - source: - openapi: ../../../openapi/referenced-specs/v2.yml - FormSubmissionList: - properties: - formSubmissions: optional> - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SkuPropertyListEnumItem: - docs: Enumerated Product variants/Options for the SKU - properties: - id: - type: string - docs: Unique identifier for a Product variant/Option - name: - type: string - docs: Name of the Product variant/Option - slug: - type: string - docs: Slug for the Product variant/Option in the Site URL structure - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - SkuPropertyList: - docs: A variant/option type for a SKU - properties: - id: - type: string - docs: Unique identifier for a collection of Product Variants - name: - type: string - docs: Name of the collection of Product Variants - enum: - docs: >- - The individual Product variants that are contained within the - collection - type: list - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ProductFieldDataTaxCategory: - enum: - - value: standard-taxable - name: StandardTaxable - - value: standard-exempt - name: StandardExempt - - value: books-religious - name: BooksReligious - - value: books-textbook - name: BooksTextbook - - clothing - - value: clothing-swimwear - name: ClothingSwimwear - - value: digital-goods - name: DigitalGoods - - value: digital-service - name: DigitalService - - value: drugs-non-prescription - name: DrugsNonPrescription - - value: drugs-prescription - name: DrugsPrescription - - value: food-bottled-water - name: FoodBottledWater - - value: food-candy - name: FoodCandy - - value: food-groceries - name: FoodGroceries - - value: food-prepared - name: FoodPrepared - - value: food-soda - name: FoodSoda - - value: food-supplements - name: FoodSupplements - - value: magazine-individual - name: MagazineIndividual - - value: magazine-subscription - name: MagazineSubscription - - value: service-admission - name: ServiceAdmission - - value: service-advertising - name: ServiceAdvertising - - value: service-dry-cleaning - name: ServiceDryCleaning - - value: service-hairdressing - name: ServiceHairdressing - - value: service-installation - name: ServiceInstallation - - value: service-miscellaneous - name: ServiceMiscellaneous - - value: service-parking - name: ServiceParking - - value: service-printing - name: ServicePrinting - - value: service-professional - name: ServiceProfessional - - value: service-repair - name: ServiceRepair - - value: service-training - name: ServiceTraining - docs: Product tax class - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ProductFieldDataEcProductType: - enum: - - ff42fee0113744f693a764e3431a9cc2 - - f22027db68002190aef89a4a2b7ac8a1 - - c599e43b1a1c34d5a323aedf75d3adf6 - - b6ccc1830db4b1babeb06a9ac5f6dd76 - docs: >- - Product - types. Enums reflect the following values in order: Physical, Digital, - Service, Advanced" - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ProductFieldData: - docs: >- - Contains content-specific details for a product, covering both standard - (e.g., title, description) and custom fields tailored to the product - setup. - properties: - name: - type: optional - docs: Name of the Product - slug: - type: optional - docs: URL structure of the Product in your site. - description: - type: optional - docs: A description of your product - shippable: - type: optional - docs: Boolean determining if the Product is shippable - sku-properties: - type: optional> - docs: Variant types to include in SKUs - category: - type: optional> - docs: The category your product belongs to. - tax-category: - type: optional - docs: Product tax class - default-sku: - type: optional - docs: The default SKU associated with this product. - ec-product-type: - type: optional - docs: >- - Product - types. Enums reflect the following values in order: Physical, - Digital, Service, Advanced" - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Product: - docs: The Product object - properties: - id: - type: optional - docs: Unique identifier for the Product - access: read-only - cmsLocaleId: - type: optional - docs: Identifier for the locale of the CMS item - access: read-only - lastPublished: - type: optional - docs: The date the Product was last published - access: read-only - lastUpdated: - type: optional - docs: The date the Product was last updated - access: read-only - createdOn: - type: optional - docs: The date the Product was created - access: read-only - isArchived: - type: optional - docs: Boolean determining if the Product is set to archived - default: false - isDraft: - type: optional - docs: Boolean determining if the Product is set to draft - default: false - fieldData: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SkuValueList: - type: map - docs: > - A mapping between SKU properties and their values, represented as - key-value pairs. Each key represents a SKU Property ID (e.g. "color") and - maps to its corresponding SKU Value ID (e.g. "blue"). This structure - defines the specific variant combination for a SKU. - SkuFieldDataPrice: - docs: price of SKU - properties: - value: - type: optional - docs: Price of SKU - unit: - type: optional - docs: Currency of Item - currency: - type: optional - docs: Currency of Item (alternative representation) - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - SkuFieldDataCompareAtPrice: - docs: comparison price of SKU - properties: - value: - type: optional - docs: Price of SKU - unit: - type: optional - docs: Currency of Item - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - SkuFieldDataEcSkuBillingMethod: - enum: - - value: one-time - name: OneTime - - subscription - docs: >- - [Billing - method](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#billing-methods)for - the SKU - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SkuFieldDataEcSkuSubscriptionPlanInterval: - enum: - - day - - week - - month - - year - docs: Interval of subscription renewal - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus: - enum: - - active - - inactive - - canceled - docs: The status of the plan - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SkuFieldDataEcSkuSubscriptionPlanPlansItem: - properties: - platform: - type: optional> - docs: The platform of the subscription plan - id: - type: optional - docs: The unique identifier of the plan - status: - type: optional - docs: The status of the plan - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - SkuFieldDataEcSkuSubscriptionPlan: - docs: >- - [Subscription - plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) - for the SKU - properties: - interval: - type: optional - docs: Interval of subscription renewal - frequency: - type: optional - docs: Frequncy of billing within interval - trial: - type: optional - docs: Number of days of a trial - plans: - type: optional> - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - SkuFieldData: - docs: Standard and Custom fields for a SKU - properties: - sku-values: optional - name: - type: string - docs: Name of the Product - slug: - type: string - docs: URL structure of the Product in your site. - price: - type: SkuFieldDataPrice - docs: price of SKU - compare-at-price: - type: optional - docs: comparison price of SKU - ec-sku-billing-method: - type: optional - docs: >- - [Billing - method](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#billing-methods)for - the SKU - ec-sku-subscription-plan: - type: optional - docs: >- - [Subscription - plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) - for the SKU - main-image: - type: optional - docs: The URL for the main image of the SKU - sku: - type: optional - docs: A unique identifier for the SKU - sku-properties: - type: optional> - docs: The properties of the SKU - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Sku: - docs: The SKU object - properties: - id: - type: optional - docs: Unique identifier for the Product - access: read-only - cmsLocaleId: - type: optional - docs: Identifier for the locale of the CMS item - access: read-only - lastPublished: - type: optional - docs: The date the Product was last published - access: read-only - lastUpdated: - type: optional - docs: The date the Product was last updated - access: read-only - createdOn: - type: optional - docs: The date the Product was created - access: read-only - fieldData: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ProductAndSkUs: - docs: A product and its SKUs. - properties: - product: optional - skus: - type: optional> - docs: A list of SKU Objects - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ProductAndSkUsList: - docs: Results from product list - properties: - items: - type: optional> - docs: >- - List of Item objects within the Collection. Contains product and skus - keys for each Item - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - PublishStatus: - enum: - - staging - - live - docs: Indicate whether your Product should be set as "staging" or "live" - default: staging - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderPrice: - properties: - unit: - type: optional - docs: The three-letter ISO currency code - value: - type: optional - docs: The numeric value in the base unit of the currency - string: - type: optional - docs: The user-facing string representation of the amount - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderAddressType: - enum: - - shipping - - billing - docs: The type of the order address (billing or shipping) - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderAddressJapanType: - enum: - - kana - - kanji - docs: >- - Represents a Japan-only address format. This field will only appear on - orders placed from Japan. - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderAddress: - docs: A customer address - properties: - type: - type: optional - docs: The type of the order address (billing or shipping) - japanType: - type: optional - docs: >- - Represents a Japan-only address format. This field will only appear on - orders placed from Japan. - addressee: - type: optional - docs: Display name on the address - line1: - type: optional - docs: The first line of the address - line2: - type: optional - docs: The second line of the address - city: - type: optional - docs: The city of the address. - state: - type: optional - docs: The state or province of the address - country: - type: optional - docs: The country of the address - postalCode: - type: optional - docs: The postal code of the address - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderPurchasedItemVariantImageFileVariantsItem: - properties: - url: - type: optional - docs: The hosted location for the Variant's image - validation: - format: uri - originalFileName: optional - size: - type: optional - docs: The image size in bytes - width: - type: optional - docs: The image width in pixels - height: - type: optional - docs: The image height in pixels - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - OrderPurchasedItemVariantImageFile: - properties: - size: - type: optional - docs: The image size in bytes - originalFileName: - type: optional - docs: the original name of the image - createdOn: - type: optional - docs: The creation timestamp of the image - contentType: - type: optional - docs: The MIME type of the image - width: - type: optional - docs: The image width in pixels - height: - type: optional - docs: The image height in pixels - variants: - type: optional> - docs: Variants of the supplied image - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - OrderPurchasedItemVariantImage: - properties: - url: - type: optional - docs: The hosted location for the Variant's image - validation: - format: uri - file: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - OrderPurchasedItem: - docs: An Item that was purchased - properties: - count: - type: optional - docs: Number of Item purchased. - rowTotal: - type: optional - docs: The total for the row - productId: - type: optional - docs: The unique identifier for the Product - access: read-only - productName: - type: optional - docs: User-facing name of the Product - productSlug: - type: optional - docs: Slug for the Product - variantId: - type: optional - docs: Identifier for the Product Variant (SKU) - variantName: - type: optional - docs: User-facing name of the Product Variant (SKU) - variantSlug: - type: optional - docs: Slug for the Product Variant (SKU) - variantSKU: - type: optional - docs: The user-defined custom SKU of the Product Variant (SKU) - variantImage: optional - variantPrice: - type: optional - docs: The price corresponding to the variant - weight: - type: optional - docs: The physical weight of the variant if provided, or null - width: - type: optional - docs: The physical width of the variant if provided, or null - height: - type: optional - docs: The physical height of the variant if provided, or null - length: - type: optional - docs: The physical length of the variant if provided, or null - source: - openapi: ../../../openapi/referenced-specs/v2.yml - StripeDetails: - docs: >- - An object with various Stripe IDs, useful for linking into the stripe - dashboard. - properties: - subscriptionId: - type: optional - docs: Stripe-generated identifier for the Subscription - paymentMethod: - type: optional - docs: Stripe-generated identifier for the PaymentMethod used - paymentIntentId: - type: optional - docs: Stripe-generated identifier for the PaymentIntent, or null - customerId: - type: optional - docs: Stripe-generated customer identifier, or null - chargeId: - type: optional - docs: Stripe-generated charge identifier, or null - disputeId: - type: optional - docs: Stripe-generated dispute identifier, or null - refundId: - type: optional - docs: Stripe-generated refund identifier, or null - refundReason: - type: optional - docs: Stripe-generated refund reason, or null - source: - openapi: ../../../openapi/referenced-specs/v2.yml - StripeCardBrand: - enum: - - Visa - - value: American Express - name: AmericanExpress - - MasterCard - - Discover - - JCB - - value: Diners Club - name: DinersClub - - Unknown - docs: The card's brand (ie. credit card network) - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - StripeCardExpires: - docs: The card's expiration date. - properties: - year: - type: optional - docs: Year that the card expires - month: - type: optional - docs: Month that the card expires - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - StripeCard: - docs: > - Details on the card used to fulfill this order, if this order was - finalized with Stripe. - properties: - last4: - type: optional - docs: The last 4 digits on the card as a string - brand: - type: optional - docs: The card's brand (ie. credit card network) - ownerName: - type: optional - docs: The name on the card. - expires: - type: optional - docs: The card's expiration date. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - PaypalDetails: - properties: - orderId: - type: optional - docs: PayPal order identifier - payerId: - type: optional - docs: PayPal payer identifier - captureId: - type: optional - docs: PayPal capture identifier - refundId: - type: optional - docs: PayPal refund identifier - refundReason: - type: optional - docs: PayPal-issued reason for the refund - disputeId: - type: optional - docs: PayPal dispute identifier - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderStatus: - enum: - - pending - - unfulfilled - - fulfilled - - disputed - - value: dispute-lost - name: DisputeLost - - refunded - docs: | - The status of the Order - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderDisputeLastStatus: - enum: - - warning_needs_response - - warning_under_review - - warning_closed - - needs_response - - under_review - - charge_refunded - - won - - lost - docs: > - If an order was disputed by the customer, then this key will be set with - the [dispute's status](https://stripe.com/docs/api#dispute_object-status). - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderShippingAddressType: - enum: - - shipping - - billing - docs: The type of the order address (billing or shipping) - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderShippingAddressJapanType: - enum: - - kana - - kanji - docs: >- - Represents a Japan-only address format. This field will only appear on - orders placed from Japan. - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderShippingAddress: - docs: The shipping address - properties: - type: - type: optional - docs: The type of the order address (billing or shipping) - japanType: - type: optional - docs: >- - Represents a Japan-only address format. This field will only appear on - orders placed from Japan. - addressee: - type: optional - docs: Display name on the address - line1: - type: optional - docs: The first line of the address - line2: - type: optional - docs: The second line of the address - city: - type: optional - docs: The city of the address. - state: - type: optional - docs: The state or province of the address - country: - type: optional - docs: The country of the address - postalCode: - type: optional - docs: The postal code of the address - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - OrderBillingAddressType: - enum: - - shipping - - billing - docs: The type of the order address (billing or shipping) - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderBillingAddressJapanType: - enum: - - kana - - kanji - docs: >- - Represents a Japan-only address format. This field will only appear on - orders placed from Japan. - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderBillingAddress: - docs: The billing address - properties: - type: - type: optional - docs: The type of the order address (billing or shipping) - japanType: - type: optional - docs: >- - Represents a Japan-only address format. This field will only appear on - orders placed from Japan. - addressee: - type: optional - docs: Display name on the address - line1: - type: optional - docs: The first line of the address - line2: - type: optional - docs: The second line of the address - city: - type: optional - docs: The city of the address. - state: - type: optional - docs: The state or province of the address - country: - type: optional - docs: The country of the address - postalCode: - type: optional - docs: The postal code of the address - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - OrderCustomerInfo: - docs: An object with the keys `fullName` and `email`. - properties: - fullName: - type: optional - docs: The full name of the Customer - email: - type: optional - docs: The Customer's email address - validation: - format: email - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - OrderMetadata: - properties: - isBuyNow: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - OrderTotalsExtrasItemType: - enum: - - discount - - value: discount-shipping - name: DiscountShipping - - shipping - - tax - docs: The type of extra item this is. - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderTotalsExtrasItem: - docs: Extra order items, includes discounts, shipping, and taxes. - properties: - type: - type: optional - docs: The type of extra item this is. - name: - type: optional - docs: A human-readable (but English) name for this extra charge. - description: - type: optional - docs: A human-readable (but English) description of this extra charge. - price: - type: optional - docs: The price for the item - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - OrderTotals: - docs: An object describing various pricing totals - properties: - subtotal: - type: optional - docs: The subtotal price - extras: - type: optional> - docs: An array of extra items, includes discounts, shipping, and taxes. - total: - type: optional - docs: The total price - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - OrderDownloadFilesItem: - properties: - id: - type: optional - docs: The unique identifier for the downloadable file - name: - type: optional - docs: The user-facing name for the downloadable file - url: - type: optional - docs: The hosted location for the downloadable file - validation: - format: uri - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Order: - properties: - orderId: - type: optional - docs: | - The order ID. Will usually be 6 hex characters, but can also be 9 - hex characters if the site has a very large number of Orders. - Randomly assigned. - access: read-only - status: - type: optional - docs: | - The status of the Order - comment: - type: optional - docs: >- - A comment string for this Order, which is editable by API user (not - used by Webflow). - orderComment: - type: optional - docs: A comment that the customer left when making their Order - acceptedOn: - type: optional - docs: The ISO8601 timestamp that an Order was placed. - fulfilledOn: - type: optional - docs: > - When an Order is marked as 'fulfilled', this field represents the - timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. - refundedOn: - type: optional - docs: >- - When an Order is marked as 'refunded', this field represents the - timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. - disputedOn: - type: optional - docs: > - When an Order is marked as 'disputed', this field represents the - timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. - disputeUpdatedOn: - type: optional - docs: > - If an Order has been disputed by the customer, this key will be set to - the ISO8601 timestamp of the last update received. If the Order is not - disputed, the key will be null. - disputeLastStatus: - type: optional - docs: > - If an order was disputed by the customer, then this key will be set - with the [dispute's - status](https://stripe.com/docs/api#dispute_object-status). - customerPaid: - type: optional - docs: The total paid by the customer - netAmount: - type: optional - docs: The net amount after application fees - applicationFee: - type: optional - docs: The application fee assessed by the platform - allAddresses: - type: optional> - docs: All addresses provided by the customer during the ordering flow. - shippingAddress: - type: optional - docs: The shipping address - billingAddress: - type: optional - docs: The billing address - shippingProvider: - type: optional - docs: > - A string editable by the API user to note the shipping provider used - (not used by Webflow). - shippingTracking: - type: optional - docs: > - A string editable by the API user to note the shipping tracking number - for the order (not used by Webflow). - shippingTrackingURL: - type: optional - validation: - format: uri - customerInfo: - type: optional - docs: An object with the keys `fullName` and `email`. - purchasedItems: - type: optional> - docs: An array of all things that the Customer purchased. - purchasedItemsCount: - type: optional - docs: The sum of all 'count' fields in 'purchasedItems'. - stripeDetails: optional - stripeCard: optional - paypalDetails: optional - customData: - type: optional>> - docs: > - An array of additional inputs for custom order data gathering. Each - object in the array represents an input with a name, and a textInput, - textArea, or checkbox value. - metadata: optional - isCustomerDeleted: - type: optional - docs: > - A boolean indicating whether the customer has been deleted from the - site. - isShippingRequired: - type: optional - docs: > - A boolean indicating whether the order contains one or more purchased - items that require shipping. - hasDownloads: - type: optional - docs: > - A boolean indicating whether the order contains one or more purchased - items that are downloadable. - paymentProcessor: - type: optional - docs: | - A string indicating the payment processor used for this order. - totals: - type: optional - docs: An object describing various pricing totals - downloadFiles: - type: optional> - docs: An array of downloadable file objects. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrderList: - docs: Results from order list - properties: - orders: - type: optional> - docs: List of orders - pagination: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - InventoryItemInventoryType: - enum: - - infinite - - finite - docs: infinite or finite - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - InventoryItem: - docs: The availabile inventory for an item - properties: - id: - type: optional - docs: Unique identifier for a SKU item - access: read-only - quantity: - type: optional - docs: >- - Total quantity of items remaining in inventory (if inventoryType is - finite) - inventoryType: - type: optional - docs: infinite or finite - source: - openapi: ../../../openapi/referenced-specs/v2.yml - EcommerceSettings: - docs: Ecommerce settings for a Webflow Site - properties: - siteId: - type: optional - docs: The identifier of the Site - access: read-only - createdOn: - type: optional - docs: Date that the Site was created on - access: read-only - defaultCurrency: - type: optional - docs: The three-letter ISO currency code for the Site - source: - openapi: ../../../openapi/referenced-specs/v2.yml - FormSubmissionTriggerPayloadSchemaItemFieldType: - enum: - - FormTextInput - - FormTextarea - - FormCheckboxInput - - FormRadioInput - - FormFileUploadInput - docs: Form field type - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - FormSubmissionTriggerPayloadSchemaItem: - properties: - fieldName: - type: optional - docs: Form field name - fieldType: - type: optional - docs: Form field type - fieldElementId: - type: optional - docs: Element ID of the Form Field - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - FormSubmissionTriggerPayload: - docs: The payload of data sent from Webflow - properties: - name: - type: optional - docs: The name of the form - siteId: - type: optional - docs: The ID of the site that the form was submitted from - data: - type: optional> - docs: The data submitted in the form - schema: - type: optional> - docs: A list of fields from the submitted form - submittedAt: - type: optional - docs: The timestamp the form was submitted - id: - type: optional - docs: the ID of the event - formId: - type: optional - docs: The ID of the form submission - formElementId: - type: optional - docs: The uniqueID of the Form element - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - FormSubmissionTrigger: - docs: The Webhook payload for when a form is submitted - properties: - triggerType: - type: optional - docs: The type of event that triggered the request - payload: - type: optional - docs: The payload of data sent from Webflow - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SitePublishPayload: - docs: The payload of data sent from Webflow - properties: - siteId: - type: optional - docs: The ID of the site that was published - publishedOn: - type: optional - docs: The timestamp of the publish event - domains: - type: optional> - docs: The domains that were published - publishedBy: - type: optional> - docs: The name andID of the user who published the site - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - SitePublish: - docs: The Webhook payload for when a Site is published - properties: - triggerType: - type: optional - docs: The type of event that triggered the request - payload: - type: optional - docs: The payload of data sent from Webflow - source: - openapi: ../../../openapi/referenced-specs/v2.yml - NewOrder: - docs: The Webhook payload for when a new order is created - properties: - triggerType: - type: optional - docs: The type of event that triggered the request - payload: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - UpdatedOrder: - docs: The Webhook payload for when an order is updated - properties: - triggerType: - type: optional - docs: The type of event that triggered the request - payload: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - SingleLocaleCreatedPayloadFieldData: - properties: - name: string - slug: string - extra-properties: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - SingleLocaleCreatedPayload: - properties: - id: - type: string - docs: Unique identifier for the Item - validation: - format: uuid - workspaceId: - type: string - docs: Unique identifier of the workspace - validation: - format: uuid - siteId: - type: string - docs: Unique identifier of the site - validation: - format: uuid - collectionId: - type: string - docs: Unique identifier of the collection - validation: - format: uuid - cmsLocaleId: - type: optional - docs: Unique identifier of the CMS locale for this item - validation: - format: uuid - lastPublished: optional - lastUpdated: optional - createdOn: optional - isArchived: optional - isDraft: optional - fieldData: SingleLocaleCreatedPayloadFieldData - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemCreated: - docs: The Webhook payload for when a Collection Item is created - properties: - triggerType: - type: literal<"collection_item_created"> - docs: The type of event that triggered the request - payload: - type: SingleLocaleCreatedPayload - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemChanged: - docs: The Webhook payload for when a Collection Item is changed - properties: - triggerType: - type: literal<"collection_item_changed"> - docs: The type of event that triggered the request - payload: - type: SingleLocaleCreatedPayload - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemRemovedPayloadFieldData: - properties: - name: string - slug: string - extra-properties: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CollectionItemRemovedPayload: - docs: The payload of data sent from Webflow - properties: - id: - type: optional - docs: The ID of the collection item that was deleted - siteId: - type: optional - docs: The ID of the site - workspaceId: - type: optional - docs: The ID of the workspace - collectionId: - type: optional - docs: The ID of the collection - cmsLocaleId: - type: optional - docs: Unique identifier of the CMS locale for this item - validation: - format: uuid - lastPublished: optional - lastUpdated: optional - createdOn: optional - isArchived: optional - isDraft: optional - fieldData: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CollectionItemRemoved: - properties: - triggerType: - type: optional - docs: The type of event that triggered the request - payload: - type: optional - docs: The payload of data sent from Webflow - source: - openapi: ../../../openapi/referenced-specs/v2.yml - PayloadFieldData: - properties: - name: string - slug: string - extra-properties: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Payload: - docs: The payload of data sent from Webflow - properties: - id: - type: optional - docs: The ID of the collection item that was unpublished - siteId: - type: optional - docs: The ID of the site - workspaceId: - type: optional - docs: The ID of the workspace - collectionId: - type: optional - docs: The ID of the collection - cmsLocaleId: - type: optional - docs: Unique identifier of the CMS locale for this item - validation: - format: uuid - lastPublished: optional - lastUpdated: optional - createdOn: optional - isArchived: optional - isDraft: optional - fieldData: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemPublished: - properties: - triggerType: - type: optional - docs: The type of event that triggered the request - payload: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CollectionItemUnpublishedPayloadFieldData: - properties: - name: string - slug: string - extra-properties: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CollectionItemUnpublishedPayload: - docs: The payload of data sent from Webflow - properties: - id: - type: optional - docs: The ID of the collection item that was unpublished - siteId: - type: optional - docs: The ID of the site - workspaceId: - type: optional - docs: The ID of the workspace - collectionId: - type: optional - docs: The ID of the collection - cmsLocaleId: - type: optional - docs: Unique identifier of the CMS locale for this item - validation: - format: uuid - lastPublished: optional - lastUpdated: optional - createdOn: optional - isArchived: optional - isDraft: optional - fieldData: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CollectionItemUnpublished: - properties: - triggerType: - type: optional - docs: The type of event that triggered the request - payload: - type: optional - docs: The payload of data sent from Webflow - source: - openapi: ../../../openapi/referenced-specs/v2.yml - PageCreatedWebhookPayload: - docs: The payload of data sent from Webflow - properties: - siteId: optional - pageId: optional - pageTitle: optional - createdOn: optional - publishedPath: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - PageCreatedWebhook: - docs: The Webhook payload for when a Page is created - properties: - triggerType: - type: optional - docs: The type of event that triggered the request - payload: - type: optional - docs: The payload of data sent from Webflow - source: - openapi: ../../../openapi/referenced-specs/v2.yml - PageMetadataUpdatedWebhookPayload: - docs: The payload of data sent from Webflow - properties: - siteId: optional - pageId: optional - pageTitle: optional - lastUpdated: optional - publishedPath: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - PageMetadataUpdatedWebhook: - docs: The Webhook payload for when a Page's metadata is updated - properties: - triggerType: - type: optional - docs: The type of event that triggered the request - payload: - type: optional - docs: The payload of data sent from Webflow - source: - openapi: ../../../openapi/referenced-specs/v2.yml - PageDeletedWebhookPayload: - docs: The payload of data sent from Webflow - properties: - siteId: optional - pageId: optional - pageTitle: optional - deletedOn: optional - publishedPath: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - PageDeletedWebhook: - docs: The Webhook payload for when a Page is deleted - properties: - triggerType: - type: optional - docs: The type of event that triggered the request - payload: - type: optional - docs: The payload of data sent from Webflow - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CommentPayloadAuthor: - properties: - userId: - type: string - docs: The unique identifier of the author - email: - type: string - docs: Email of the author - name: - type: string - docs: Name of the author - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CommentPayloadMentionedUsersItem: - properties: - userId: - type: string - docs: The unique identifier of the mentioned user - email: - type: string - docs: Email of the user - name: - type: string - docs: Name of the User - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CommentPayload: - docs: > - The comment webhook payload contains data for the thread and for replies. - Check the type to determine if the payload is for a thread or a reply. - The webhook payload may be delayed by up to 5 minutes. - properties: - threadId: - type: optional - docs: Unique identifier for the comment thread - access: read-only - commentId: - type: optional - docs: Unique identifier for the comment reply - access: read-only - type: - type: optional - docs: The type of comment payload - access: read-only - siteId: - type: optional - docs: The site unique identifier - access: read-only - pageId: - type: optional - docs: The page unique identifier - access: read-only - localeId: - type: optional - docs: The locale unique identifier - access: read-only - itemId: - type: optional - docs: The item unique identifier - access: read-only - breakpoint: - type: optional - docs: The breakpoint the comment was left on - access: read-only - url: - type: optional - docs: The URL of the page the comment was left on - access: read-only - content: - type: string - docs: The content of the comment reply - isResolved: - type: boolean - docs: Boolean determining if the comment thread is resolved - default: false - author: CommentPayloadAuthor - mentionedUsers: - docs: >- - List of mentioned users. This is an empty array until email - notifications are sent, which can take up to 5 minutes after the - comment is created. - type: list - createdOn: - type: optional - docs: The date the item was created - access: read-only - lastUpdated: - type: optional - docs: The date the item was last updated - access: read-only - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Comment: - docs: The Webhook payload for when a comment thread or reply is made on a Site - properties: - triggerType: - type: optional - docs: The type of event that triggered the request - payload: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/api.yml b/.mock/definition/api.yml deleted file mode 100644 index de74f2d..0000000 --- a/.mock/definition/api.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: api -error-discrimination: - strategy: status-code -display-name: Data API -environments: - Data API: - urls: - Base: https://api.webflow.com/v2 - Data API: https://api.webflow.com/v2 - Content Delivery API: https://api-cdn.webflow.com/v2 -default-environment: Data API -default-url: Base -auth-schemes: - BearerToken: - scheme: bearer - token: - name: accessToken -auth: BearerToken diff --git a/.mock/definition/assets.yml b/.mock/definition/assets.yml deleted file mode 100644 index dcdff94..0000000 --- a/.mock/definition/assets.yml +++ /dev/null @@ -1,487 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/assets - method: GET - auth: - - OAuth2: - - assets:read - docs: | - List of assets uploaded to a site - - Required scope | `assets:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Assets - request: - name: AssetsListRequest - query-parameters: - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - response: - docs: Request was successful - type: root.Assets - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - query-parameters: - offset: 1 - limit: 1 - response: - body: - assets: - - id: 63e5889e7fe4eafa7384cea4 - contentType: image/png - size: 2212772 - siteId: 63938b302ea6b0aa6f3d8745 - hostedUrl: >- - https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg - originalFileName: Candy-Wrapper.svg - displayName: 63e5889e7fe4eafa7384cea4_Candy-Wrapper.png - lastUpdated: '2023-03-01T23:42:57Z' - createdOn: '2023-02-09T23:58:22Z' - variants: - - hostedUrl: >- - https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - originalFileName: >- - Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - displayName: >- - 660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - format: png - width: 500 - height: 900 - quality: 100 - altText: A single candy wrapper - - id: 63e5889e7fe4eafa7384cea5 - contentType: image/png - size: 2212772 - siteId: 63938b302ea6b0aa6f3d8745 - hostedUrl: >- - https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg - originalFileName: Gum-Wrapper.svg - displayName: 63e5889e7fe4eafa7384cea5_Gum-Wrapper.png - lastUpdated: '2023-03-01T23:42:57Z' - createdOn: '2023-02-09T23:58:22Z' - variants: - - hostedUrl: >- - https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - originalFileName: >- - Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - displayName: >- - 660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - format: png - width: 500 - height: 900 - quality: 100 - altText: A single gum wrapper - pagination: - limit: 2 - offset: 0 - total: 2 - create: - path: /sites/{site_id}/assets - method: POST - auth: - - OAuth2: - - assets:write - docs: > - The first step in uploading an asset to a site. - - - - This endpoint generates a response with the following information: - `uploadUrl` and `uploadDetails`. - - - - Use these properties in the header of a [POST request to Amazson - s3](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) - to complete the upload. - - - - To learn more about how to upload assets to Webflow, see our [assets - guide](/data/docs/working-with-assets). - - Required scope | `assets:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Upload Asset - request: - name: AssetsCreateRequest - body: - properties: - fileName: - type: string - docs: >- - File name including file extension. File names must be less than - 100 characters. - fileHash: - type: string - docs: MD5 hash of the file - parentFolder: - type: optional - docs: ID of the Asset folder (optional) - content-type: application/json - response: - docs: Request was successful - type: root.AssetUpload - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - fileName: file.png - fileHash: 3c7d87c9575702bc3b1e991f4d3c638e - response: - body: - uploadDetails: - acl: public-read - bucket: webflow-bucket-name - X-Amz-Algorithm: AWS4-HMAC-SHA256 - X-Amz-Credential: ///s3/aws4_request - X-Amz-Date: - key: /_ - Policy: - X-Amz-Signature: - success_action_status: '201' - content-type: image/png - Cache-Control: max-age=31536000, must-revalidate - contentType: image/png - id: 64358b9544249dc43d37d2b7 - parentFolder: 6436b1ce5281cace05b65aea - uploadUrl: >- - https://s3.amazonaws.com/webflow-dev-assets/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png - assetUrl: >- - https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d907ab9e91e3e9f56385e_paranoidAndroid-2024.png - hostedUrl: >- - https://dev-assets.website-files.com/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png - originalFileName: file.png - createdOn: '2023-04-11T16:32:21Z' - lastUpdated: '2023-04-12T20:31:03Z' - get: - path: /assets/{asset_id} - method: GET - auth: - - OAuth2: - - assets:read - docs: | - Get details about an asset - - Required scope | `assets:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - asset_id: - type: string - docs: Unique identifier for an Asset on a site - display-name: Get Asset - response: - docs: Request was successful - type: root.Asset - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - asset_id: 580e63fc8c9a982ac9b8b745 - response: - body: - id: 63e5889e7fe4eafa7384cea4 - contentType: image/png - size: 2212772 - siteId: 63938b302ea6b0aa6f3d8745 - hostedUrl: >- - https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg - originalFileName: Candy-Wrapper.svg - displayName: 63e5889e7fe4eafa7384cea4_Candy-Wrapper.png - lastUpdated: '2023-03-01T23:42:57Z' - createdOn: '2023-02-09T23:58:22Z' - variants: - - hostedUrl: >- - https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - originalFileName: Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - displayName: >- - 660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - format: png - width: 500 - height: 900 - quality: 100 - error: error - altText: A single candy wrapper - delete: - path: /assets/{asset_id} - method: DELETE - auth: - - OAuth2: - - assets:write - docs: | - Delete an Asset - - Required Scope: `assets: write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - asset_id: - type: string - docs: Unique identifier for an Asset on a site - display-name: Delete Asset - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - asset_id: 580e63fc8c9a982ac9b8b745 - update: - path: /assets/{asset_id} - method: PATCH - auth: - - OAuth2: - - assets:write - docs: | - Update details of an Asset. - - Required scope | `assets:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - asset_id: - type: string - docs: Unique identifier for an Asset on a site - display-name: Update Asset - request: - name: AssetsUpdateRequest - body: - properties: - localeId: - type: optional - docs: >- - Unique identifier for a specific locale. Applicable, when using - localization. - displayName: - type: optional - docs: A human readable name for the asset - content-type: application/json - response: - docs: Request was successful - type: root.Asset - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - asset_id: 580e63fc8c9a982ac9b8b745 - request: {} - response: - body: - id: 63e5889e7fe4eafa7384cea4 - contentType: image/png - size: 2212772 - siteId: 63938b302ea6b0aa6f3d8745 - hostedUrl: >- - https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg - originalFileName: Candy-Wrapper.svg - displayName: 63e5889e7fe4eafa7384cea4_Candy-Wrapper.png - lastUpdated: '2023-03-01T23:42:57Z' - createdOn: '2023-02-09T23:58:22Z' - variants: - - hostedUrl: >- - https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - originalFileName: Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - displayName: >- - 660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png - format: png - width: 500 - height: 900 - quality: 100 - error: error - altText: A single candy wrapper - list-folders: - path: /sites/{site_id}/asset_folders - method: GET - auth: - - OAuth2: - - assets:read - docs: | - List Asset Folders within a given site - - Required scope | `assets:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Asset Folders - response: - docs: Request was successful - type: root.AssetFolderList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - assetFolders: - - id: 6390c49774a71f0e3c1a08ee - displayName: emoji icons - parentFolder: 6390c49774a71f99f21a08eb - assets: - - 63e5889e7fe4eafa7384cea4 - - 659595234426a9fcbad57043 - siteId: 6390c49674a71f84b51a08d8 - createdOn: '2018-10-14T21:55:49Z' - lastUpdated: '2022-12-07T16:51:37Z' - pagination: - limit: 1 - offset: 0 - total: 1 - create-folder: - path: /sites/{site_id}/asset_folders - method: POST - auth: - - OAuth2: - - assets:write - docs: | - Create an Asset Folder within a given site - - Required scope | `assets:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Create Asset Folder - request: - name: AssetsCreateFolderRequest - body: - properties: - displayName: - type: string - docs: A human readable name for the Asset Folder - parentFolder: - type: optional - docs: >- - An (optional) pointer to a parent Asset Folder (or null for - root) - content-type: application/json - response: - docs: Request was successful - type: root.AssetFolder - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - displayName: my asset folder - response: - body: - id: 6390c49774a71f0e3c1a08ee - displayName: emoji icons - parentFolder: 6390c49774a71f99f21a08eb - assets: - - 63e5889e7fe4eafa7384cea4 - - 659595234426a9fcbad57043 - siteId: 6390c49674a71f84b51a08d8 - createdOn: '2018-10-14T21:55:49Z' - lastUpdated: '2022-12-07T16:51:37Z' - get-folder: - path: /asset_folders/{asset_folder_id} - method: GET - auth: - - OAuth2: - - assets:read - docs: | - Get details about a specific Asset Folder - - Required scope | `assets:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - asset_folder_id: - type: string - docs: Unique identifier for an Asset Folder - display-name: Get Asset Folder - response: - docs: Request was successful - type: root.AssetFolder - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - asset_folder_id: 6390c49774a71f0e3c1a08ee - response: - body: - id: 6390c49774a71f0e3c1a08ee - displayName: emoji icons - parentFolder: 6390c49774a71f99f21a08eb - assets: - - 63e5889e7fe4eafa7384cea4 - - 659595234426a9fcbad57043 - siteId: 6390c49674a71f84b51a08d8 - createdOn: '2018-10-14T21:55:49Z' - lastUpdated: '2022-12-07T16:51:37Z' - source: - openapi: ../../../openapi/referenced-specs/v2.yml - display-name: Assets -docs: Assets are files that are uploaded to your Webflow account. diff --git a/.mock/definition/collections.yml b/.mock/definition/collections.yml deleted file mode 100644 index b9ee7cd..0000000 --- a/.mock/definition/collections.yml +++ /dev/null @@ -1,350 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/collections - method: GET - auth: - - OAuth2: - - cms:read - docs: | - List of all Collections within a Site. - - Required scope | `cms:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Collections - response: - docs: Request was successful - type: root.CollectionList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - collections: - - id: 63692ab61fb2852f582ba8f5 - displayName: Products - singularName: Product - slug: product - createdOn: '2019-06-12T13:35:14Z' - lastUpdated: '2022-11-17T15:08:50Z' - - id: 63692ab61fb2856e6a2ba8f6 - displayName: Categories - singularName: Category - slug: category - createdOn: '2019-06-12T13:35:14Z' - lastUpdated: '2022-11-17T15:08:50Z' - - id: 63692ab61fb285a8562ba8f4 - displayName: SKUs - singularName: SKU - slug: sku - createdOn: '2019-06-12T13:35:14Z' - lastUpdated: '2022-11-17T15:08:50Z' - create: - path: /sites/{site_id}/collections - method: POST - auth: - - OAuth2: - - cms:write - docs: > - Create a Collection for a site with collection fields. - - - Each collection includes the required _name_ and _slug_ fields, which - are generated automatically. You can update the `displayName` of these - fields, but the slug for them cannot be changed. Fields slugs are - automatically converted to lowercase. Spaces in slugs are replaced with - hyphens. - - - Required scope | `cms:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Create Collection - request: - name: CollectionsCreateRequest - body: - properties: - displayName: - type: string - docs: Name of the collection. Each collection name must be distinct. - singularName: - type: string - docs: Singular name of each item. - slug: - type: optional - docs: Part of a URL that identifier - fields: - type: optional> - docs: An array of custom fields to add to the collection - content-type: application/json - response: - docs: Request was successful - type: root.Collection - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - displayName: Blog Posts - singularName: Blog Post - slug: posts - fields: - - isRequired: true - type: PlainText - displayName: Title - helpText: The title of the blog post - - isRequired: true - type: RichText - displayName: Content - helpText: The content of the blog post - - isRequired: true - type: Reference - displayName: Author - helpText: The author of the blog post - metadata: - collectionId: 23cc2d952d4e4631ffd4345d2743db4e - response: - body: - id: 562ac0395358780a1f5e6fbd - displayName: Blog Posts - singularName: Blog Post - slug: posts - createdOn: '2016-10-24T19:41:48Z' - lastUpdated: '2016-10-24T19:42:38Z' - fields: - - id: id - isRequired: true - isEditable: true - type: PlainText - slug: title - displayName: Title - helpText: The title of the blog post - - id: id - isRequired: true - isEditable: true - type: RichText - slug: content - displayName: Content - helpText: The content of the blog post - - id: id - isRequired: true - isEditable: true - type: Reference - slug: author - displayName: Author - helpText: The author of the blog post - get: - path: /collections/{collection_id} - method: GET - auth: - - OAuth2: - - cms:read - docs: | - Get the full details of a collection from its ID. - - Required scope | `cms:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: Get Collection Details - response: - docs: Request was successful - type: root.Collection - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - response: - body: - id: 7f15043107e2fc95644e93807ee25dd6 - displayName: Guide Entries - singularName: Guide Entry - slug: guide-entry - createdOn: '2024-04-12T12:42:00Z' - lastUpdated: '2024-04-12T12:42:00Z' - fields: - - id: 5e2a1b3c4d5e6f7890a1b2c3 - isRequired: true - isEditable: true - type: PlainText - slug: name - displayName: Entry Title - helpText: Name of the entry. - - id: 5e2a1b3c4d5e6f7890a1b2c4 - isRequired: true - isEditable: true - type: PlainText - slug: slug - displayName: Slug - helpText: Slug of the entry. - - id: 6f7e8d9c0b1a2e3d4c5b6a7f - isRequired: false - isEditable: true - type: PlainText - slug: summary - displayName: Summary - helpText: A short summary of the entry. - - id: 1a2b3c4d5e6f7a8b9c0d1e2f - isRequired: false - isEditable: true - type: RichText - slug: entry-html - displayName: Entry HTML - helpText: The HTML content of the entry. - - id: 7e8d9c0b1a2e3d4c5b6a7f8e - isRequired: false - isEditable: true - type: Image - slug: illustration-image - displayName: Illustration Image - helpText: An image of the entry. - - id: 2f3e4d5c6b7a8e9d0c1b2a3f - isRequired: false - isEditable: true - type: VideoLink - slug: demonstration-video - displayName: Demonstration Video - helpText: A video of the entry. - - id: 8e9d0c1b2a3f4e5d6c7b8a9e - isRequired: false - isEditable: true - type: Link - slug: more-info-link - displayName: More Info Link - helpText: A link to more information about the entry. - - id: 3f4e5d6c7b8a9e0d1c2b3a4f - isRequired: false - isEditable: true - type: Number - slug: importance-level - displayName: Importance Level - helpText: The importance level of the entry. - - id: 9e0d1c2b3a4f5e6d7c8b9a0e - isRequired: false - isEditable: true - type: Switch - slug: is-essential - displayName: Is Essential - helpText: Is this entry essential? - - id: 4f5e6d7c8b9a0e1d2c3b4a5f - isRequired: false - isEditable: true - type: Color - slug: first-mentioned - displayName: First Mentioned - helpText: Date of the first mention of the subject. - - id: 0e1d2c3b4a5f6e7d8c9b0a1e - isRequired: false - isEditable: true - type: Color - slug: towel-color - displayName: Towel Color - helpText: The color of the towel. - - id: 5f6e7d8c9b0a1e2d3c4b5a6f - isRequired: false - isEditable: true - type: Reference - slug: related-entry - displayName: Related Entry - helpText: A related entry. - - id: 1e2d3c4b5a6f7e8d9c0b1a2f - isRequired: false - isEditable: true - type: MultiReference - slug: mentioned-in-entries - displayName: Mentioned In Entries - helpText: Entries that mention this subject. - - id: 6f7e8d9c0b1a2e3d4c5b6a8f - isRequired: false - isEditable: true - type: Option - slug: item-type - displayName: Item Type - helpText: The type of item. - - id: 2e3d4c5b6a7f8e9d0c1b2a4f - isRequired: false - isEditable: true - type: File - slug: guide-file - displayName: Guide File - helpText: helpText - - id: 7f8e9d0c1b2a3f4e5d6c8b9e - isRequired: false - isEditable: true - type: Email - slug: contributor-email - displayName: Contributor Email - helpText: helpText - - id: 3a4f5e6d7c8b9a0e1d2c4b5f - isRequired: false - isEditable: true - type: Phone - slug: emergency-contact - displayName: Emergency Contact - helpText: helpText - delete: - path: /collections/{collection_id} - method: DELETE - auth: - - OAuth2: - - cms:write - docs: | - Delete a collection using its ID. - - Required scope | `cms:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: Delete Collection - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - source: - openapi: ../../../openapi/referenced-specs/v2.yml - display-name: Collections -docs: Collections are CMS collections of items. diff --git a/.mock/definition/collections/fields.yml b/.mock/definition/collections/fields.yml deleted file mode 100644 index 8d83b9f..0000000 --- a/.mock/definition/collections/fields.yml +++ /dev/null @@ -1,212 +0,0 @@ -imports: - root: ../__package__.yml -service: - auth: false - base-path: '' - endpoints: - create: - path: /collections/{collection_id}/fields - method: POST - auth: - - OAuth2: - - cms:write - docs: > - Create a custom field in a collection. - - - Field validation is currently not available through the API. - - - Bulk creation of fields is not supported with this endpoint. To add - multiple fields at once, include them when you [create the - collection.](/data/v2.0.0/reference/cms/collections/create) - - - Required scope | `cms:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: Create Collection Field - request: - body: root.FieldCreate - content-type: application/json - response: - docs: Request was successful - type: root.FieldCreate - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - name: StaticField - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - id: 562ac0395358780a1f5e6fbc - isEditable: true - isRequired: false - type: RichText - displayName: Post Body - helpText: Add the body of your post here - response: - body: - id: 562ac0395358780a1f5e6fbc - isEditable: true - isRequired: false - type: RichText - displayName: Post Body - helpText: Add the body of your post here - - name: OptionField - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - id: 562ac0395358780a1f5e6fbc - isEditable: true - isRequired: false - type: Option - displayName: Post Type - helpText: Add the body of your post here - metadata: - options: - - name: Feature - - name: News - - name: Product Highlight - response: - body: - id: 562ac0395358780a1f5e6fbc - isEditable: true - isRequired: false - type: Option - displayName: Post Type - helpText: Add the body of your post here - metadata: - options: - - name: Feature - - name: News - - name: Product Highlight - - name: ReferenceField - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - id: 562ac0395358780a1f5e6fbd - isEditable: true - isRequired: false - type: Reference - displayName: Author - helpText: Add the post author here - metadata: - collectionId: 63692ab61fb2852f582ba8f5 - response: - body: - id: 562ac0395358780a1f5e6fbd - isEditable: true - isRequired: false - type: Reference - displayName: Author - helpText: Add the post author here - metadata: - collectionId: 63692ab61fb2852f582ba8f5 - delete: - path: /collections/{collection_id}/fields/{field_id} - method: DELETE - auth: - - OAuth2: - - cms:write - docs: > - Delete a custom field in a collection. This endpoint does not currently - support bulk deletion. - - - Required scope | `cms:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - field_id: - type: string - docs: Unique identifier for a Field in a collection - display-name: Delete Collection Field - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - field_id: 580e63fc8c9a982ac9b8b745 - update: - path: /collections/{collection_id}/fields/{field_id} - method: PATCH - auth: - - OAuth2: - - cms:write - docs: | - Update a custom field in a collection. - - Required scope | `cms:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - field_id: - type: string - docs: Unique identifier for a Field in a collection - display-name: Update Collection Field - request: - name: FieldUpdate - body: - properties: - isRequired: - type: optional - docs: Define whether a field is required in a collection - displayName: - type: optional - docs: The name of a field - helpText: - type: optional - docs: Additional text to help anyone filling out this field - content-type: application/json - response: - docs: Request was successful - type: root.Field - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - field_id: 580e63fc8c9a982ac9b8b745 - request: - isRequired: false - displayName: Post Body - helpText: Add the body of your post here - response: - body: - id: 75821f618da60c18383330bcc0ca488b - isRequired: false - isEditable: true - type: RichText - slug: post-body - displayName: Post Body - helpText: Add the body of your post here - validations: - additionalProperties: additionalProperties - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/collections/items.yml b/.mock/definition/collections/items.yml deleted file mode 100644 index 57e6402..0000000 --- a/.mock/definition/collections/items.yml +++ /dev/null @@ -1,2145 +0,0 @@ -imports: - root: ../__package__.yml -types: - ItemsListItemsRequestSortBy: - enum: - - lastPublished - - name - - slug - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ItemsListItemsRequestSortOrder: - enum: - - asc - - desc - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Multiple Items: - properties: - items: - type: optional> - docs: An array of items to create - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - ItemsCreateItemRequestBody: - discriminated: false - union: - - root.CollectionItemPostSingle - - type: Multiple Items - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ItemsDeleteItemsRequestItemsItem: - properties: - id: - type: string - docs: Unique identifier for the Item - cmsLocaleIds: - type: optional> - docs: Array of identifiers for the locales where the item will be created - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - ItemsUpdateItemsResponse: - discriminated: false - union: - - type: root.CollectionItem - - type: root.CollectionItemList - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ItemsListItemsLiveRequestSortBy: - enum: - - lastPublished - - name - - slug - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ItemsListItemsLiveRequestSortOrder: - enum: - - asc - - desc - source: - openapi: ../../../openapi/referenced-specs/v2.yml - Multiple Live Items: - properties: - items: - type: optional> - docs: List of collection items to create - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - ItemsCreateItemLiveRequestBody: - discriminated: false - union: - - type: root.CollectionItem - - type: Multiple Live Items - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ItemsDeleteItemsLiveRequestItemsItem: - properties: - id: - type: string - docs: Unique identifier for the Item - cmsLocaleIds: - type: optional> - docs: Array of identifiers for the locales where the item will be created - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Single CMS Item: - properties: - name: - type: string - docs: The name of the item. - slug: - type: string - docs: >- - URL slug for the item in your site. - - Note: Updating the item slug will break all links referencing the old - slug. - extra-properties: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CreateBulkCollectionItemRequestBodyFieldDataItem: - docs: A single CMS item to create - properties: - name: - type: string - docs: The name of the item. - slug: - type: string - docs: >- - URL slug for the item in your site. - - Note: Updating the item slug will break all links referencing the old - slug. - extra-properties: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - CreateBulkCollectionItemRequestBodyFieldData: - discriminated: false - union: - - type: Single CMS Item - - docs: A list of CMS items to create - type: list - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Item IDs: - docs: An array of Item IDs in a single locale - properties: - itemIds: optional> - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - ItemsPublishItemRequestItemsItemsItem: - properties: - id: - type: string - docs: The ID of the CMS item - cmsLocaleIds: - type: optional> - docs: Array of identifiers for the locales where the item will be published - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - Item IDs with Locales: - docs: An array of Item IDs with included `cmsLocaleIds` - properties: - items: optional> - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - ItemsPublishItemRequest: - discriminated: false - union: - - type: Item IDs - docs: An array of Item IDs in a single locale - - type: Item IDs with Locales - docs: An array of Item IDs with included `cmsLocaleIds` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ItemsPublishItemResponse: - properties: - publishedItemIds: optional> - errors: optional> - source: - openapi: ../../../openapi/referenced-specs/v2.yml -service: - auth: false - base-path: '' - endpoints: - list-items: - path: /collections/{collection_id}/items - method: GET - auth: - - OAuth2: - - cms:read - docs: | - List of all Items within a Collection. - - Required scope | `CMS:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: List Collection Items - request: - name: ItemsListItemsRequest - query-parameters: - cmsLocaleId: - type: optional - docs: >- - Unique identifier for a CMS Locale. This UID is different from the - Site locale identifier and is listed as `cmsLocaleId` in the Sites - response. To query multiple locales, input a comma separated - string. - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - name: - type: optional - docs: Filter by the exact name of the item(s) - slug: - type: optional - docs: Filter by the exact slug of the item - lastPublished: - type: optional - docs: Filter by the last published date of the item(s) - sortBy: - type: optional - docs: Sort results by the provided value - sortOrder: - type: optional - docs: Sorts the results by asc or desc - response: - docs: Request was successful - type: root.CollectionItemList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - cmsLocaleId: cmsLocaleId - offset: 1 - limit: 1 - name: name - slug: slug - sortBy: lastPublished - sortOrder: asc - response: - body: - items: - - id: 62b720ef280c7a7a3be8cabe - cmsLocaleId: 66f6e966c9e1dc700a857ca3 - lastPublished: '2022-06-30T13:35:20.878Z' - lastUpdated: '2022-06-25T14:51:27.809Z' - createdOn: '2022-06-25T14:51:27.809Z' - isArchived: false - isDraft: false - fieldData: - name: Senior Data Analyst - slug: senior-data-analyst - url: https://boards.greenhouse.io/webflow/jobs/26567701 - department: Data - - id: 62c880ef281c7b7b4cf9dabc - cmsLocaleId: 66f6e966c9e1dc700a857ca3 - lastPublished: '2023-04-15T10:25:18.123Z' - lastUpdated: '2023-04-10T11:45:30.567Z' - createdOn: '2023-04-10T11:45:30.567Z' - isArchived: false - isDraft: false - fieldData: - name: Product Manager - slug: product-manager - url: https://boards.greenhouse.io/webflow/jobs/31234567 - department: Product - pagination: - limit: 25 - offset: 0 - total: 2 - create-item: - path: /collections/{collection_id}/items - method: POST - auth: - - OAuth2: - - cms:write - docs: > - Create Item(s) in a Collection. - - - - To create items across multiple locales, please use [this - endpoint.](/data/reference/cms/collection-items/staged-items/create-items) - - - Required scope | `CMS:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: Create Collection Item(s) - request: - body: ItemsCreateItemRequestBody - query-parameters: - skipInvalidFiles: - type: optional - default: true - docs: >- - When true, invalid files are skipped and processing continues. - When false, the entire request fails if any file is invalid. - name: ItemsCreateItemRequest - content-type: application/json - response: - docs: Request was successful - type: root.CollectionItem - status-code: 202 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - name: SingleItem - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - isArchived: false - isDraft: false - fieldData: - name: The Hitchhiker's Guide to the Galaxy - slug: hitchhikers-guide-to-the-galaxy - plain-text: Don't Panic. - rich-text: >- -

A Guide to Interstellar Travel

A towel is about the - most massively useful thing an interstellar hitchhiker can have. - Don't forget yours!

- main-image: - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - image-gallery: - - fileId: 62b720ef280c7a7a3be8cabd - url: /files/62b720ef280c7a7a3be8cabd_image.png - - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 - official-site: >- - https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy - contact-email: zaphod.beeblebrox@heartofgold.gov - support-phone: 424-242-4242 - answer-to-everything: 42 - release-date: '1979-10-12T00:00:00.000Z' - is-featured: true - brand-color: '#000000' - category: 62b720ef280c7a7a3be8cabf - author: 62b720ef280c7a7a3be8cab0 - tags: - - 62b720ef280c7a7a3be8cab1 - - 62b720ef280c7a7a3be8cab2 - downloadable-asset: - fileId: 62b720ef280c7a7a3be8cab3 - url: /files/62b720ef280c7a7a3be8cab3_document.pdf - response: - body: - id: 42b720ef280c7a7a3be8cabe - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2022-11-29T16:22:43.159Z' - lastUpdated: '2022-11-17T17:19:43.282Z' - createdOn: '2022-11-17T17:11:57.148Z' - isArchived: false - isDraft: false - fieldData: - name: The Hitchhiker's Guide to the Galaxy - slug: hitchhikers-guide-to-the-galaxy - plain-text: Don't Panic. - rich-text: >- -

A Guide to Interstellar Travel

A towel is about the - most massively useful thing an interstellar hitchhiker can - have. Don't forget yours!

- main-image: - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - image-gallery: - - fileId: 62b720ef280c7a7a3be8cabd - url: /files/62b720ef280c7a7a3be8cabd_image.png - - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 - official-site: >- - https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy - contact-email: zaphod.beeblebrox@heartofgold.gov - support-phone: 424-242-4242 - answer-to-everything: 42 - release-date: '1979-10-12T00:00:00.000Z' - is-featured: true - brand-color: '#000000' - category: 62b720ef280c7a7a3be8cabf - author: 62b720ef280c7a7a3be8cab0 - tags: - - 62b720ef280c7a7a3be8cab1 - - 62b720ef280c7a7a3be8cab2 - downloadable-asset: - fileId: 62b720ef280c7a7a3be8cab3 - url: /files/62b720ef280c7a7a3be8cab3_document.pdf - - name: MultipleItems - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - items: - - isArchived: false - isDraft: false - fieldData: - name: Senior Data Analyst - slug: senior-data-analyst - url: https://boards.greenhouse.io/webflow/jobs/26567701 - department: Data - - isArchived: false - isDraft: false - fieldData: - name: Product Manager - slug: product-manager - url: https://boards.greenhouse.io/webflow/jobs/31234567 - department: Product - response: - body: - id: id - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' - delete-items: - path: /collections/{collection_id}/items - method: DELETE - auth: - - OAuth2: - - cms:write - docs: > - Delete Items from a Collection. - - - Items will only be deleted in the primary - locale unless a `cmsLocaleId` is included in the request. - - - Required scope | `CMS:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: Delete Collection Items - request: - name: ItemsDeleteItemsRequest - body: - properties: - items: list - content-type: application/json - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - items: - - id: 580e64008c9a982ac9b8b754 - update-items: - path: /collections/{collection_id}/items - method: PATCH - auth: - - OAuth2: - - cms:write - docs: > - Update a single item or multiple items in a Collection. - - - The limit for this endpoint is 100 items. - - - Items will only be updated in the primary - locale, unless a `cmsLocaleId` is included in the request. - - - Required scope | `CMS:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: Update Collection Items - request: - name: ItemsUpdateItemsRequest - query-parameters: - skipInvalidFiles: - type: optional - default: true - docs: >- - When true, invalid files are skipped and processing continues. - When false, the entire request fails if any file is invalid. - body: - properties: - items: optional> - content-type: application/json - response: - docs: Request was successful - type: ItemsUpdateItemsResponse - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - name: LocalizedItems - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - response: - body: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - pagination: - limit: 25 - offset: 0 - total: 4 - - name: MultipleItems - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - items: - - id: 580e64008c9a982ac9b8b754 - isArchived: false - isDraft: false - fieldData: - name: Senior Data Analyst - slug: senior-data-analyst - url: https://boards.greenhouse.io/webflow/jobs/26567701 - department: Data - - id: 580e64008c9a982ac9b8b754 - isArchived: false - isDraft: false - fieldData: - name: Product Manager - slug: product-manager - url: https://boards.greenhouse.io/webflow/jobs/31234567 - department: Product - response: - body: - items: - - id: 62b720ef280c7a7a3be8cabe - cmsLocaleId: 66f6e966c9e1dc700a857ca3 - lastPublished: '2022-06-30T13:35:20.878Z' - lastUpdated: '2022-06-25T14:51:27.809Z' - createdOn: '2022-06-25T14:51:27.809Z' - isArchived: false - isDraft: false - fieldData: - name: Senior Data Analyst - slug: senior-data-analyst - url: https://boards.greenhouse.io/webflow/jobs/26567701 - department: Data - - id: 62c880ef281c7b7b4cf9dabc - cmsLocaleId: 66f6e966c9e1dc700a857ca3 - lastPublished: '2023-04-15T10:25:18.123Z' - lastUpdated: '2023-04-10T11:45:30.567Z' - createdOn: '2023-04-10T11:45:30.567Z' - isArchived: false - isDraft: false - fieldData: - name: Product Manager - slug: product-manager - url: https://boards.greenhouse.io/webflow/jobs/31234567 - department: Product - pagination: - limit: 25 - offset: 0 - total: 2 - list-items-live: - path: /collections/{collection_id}/items/live - method: GET - auth: - - OAuth2: - - cms:read - docs: | - List all published items in a collection. - - - Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. - - - Required scope | `CMS:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: List Live Collection Items - request: - name: ItemsListItemsLiveRequest - query-parameters: - cmsLocaleId: - type: optional - docs: >- - Unique identifier for a CMS Locale. This UID is different from the - Site locale identifier and is listed as `cmsLocaleId` in the Sites - response. To query multiple locales, input a comma separated - string. - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - name: - type: optional - docs: Filter by the exact name of the item(s) - slug: - type: optional - docs: Filter by the exact slug of the item - lastPublished: - type: optional - docs: Filter by the last published date of the item(s) - sortBy: - type: optional - docs: Sort results by the provided value - sortOrder: - type: optional - docs: Sorts the results by asc or desc - response: - docs: Request was successful - type: root.CollectionItemList - status-code: 200 - url: Data API - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - cmsLocaleId: cmsLocaleId - offset: 1 - limit: 1 - name: name - slug: slug - sortBy: lastPublished - sortOrder: asc - response: - body: - items: - - id: 62b720ef280c7a7a3be8cabe - cmsLocaleId: 66f6e966c9e1dc700a857ca3 - lastPublished: '2022-06-30T13:35:20.878Z' - lastUpdated: '2022-06-25T14:51:27.809Z' - createdOn: '2022-06-25T14:51:27.809Z' - isArchived: false - isDraft: false - fieldData: - name: Senior Data Analyst - slug: senior-data-analyst - url: https://boards.greenhouse.io/webflow/jobs/26567701 - department: Data - - id: 62c880ef281c7b7b4cf9dabc - cmsLocaleId: 66f6e966c9e1dc700a857ca3 - lastPublished: '2023-04-15T10:25:18.123Z' - lastUpdated: '2023-04-10T11:45:30.567Z' - createdOn: '2023-04-10T11:45:30.567Z' - isArchived: false - isDraft: false - fieldData: - name: Product Manager - slug: product-manager - url: https://boards.greenhouse.io/webflow/jobs/31234567 - department: Product - pagination: - limit: 25 - offset: 0 - total: 2 - create-item-live: - path: /collections/{collection_id}/items/live - method: POST - auth: - - OAuth2: - - cms:write - docs: > - Create item(s) in a collection that will be immediately published to the - live site. - - - - To create items across multiple locales, [please use this - endpoint.](/data/reference/cms/collection-items/staged-items/create-items) - - - - Required scope | `CMS:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: Create Live Collection Item(s) - request: - body: ItemsCreateItemLiveRequestBody - query-parameters: - skipInvalidFiles: - type: optional - default: true - docs: >- - When true, invalid files are skipped and processing continues. - When false, the entire request fails if any file is invalid. - name: ItemsCreateItemLiveRequest - content-type: application/json - response: - docs: Request was successful - type: root.CollectionItem - status-code: 202 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - name: SingleItem - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - isArchived: false - isDraft: false - fieldData: - name: The Hitchhiker's Guide to the Galaxy - slug: hitchhikers-guide-to-the-galaxy - plain-text: Don't Panic. - rich-text: >- -

A Guide to Interstellar Travel

A towel is about the - most massively useful thing an interstellar hitchhiker can have. - Don't forget yours!

- main-image: - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - image-gallery: - - fileId: 62b720ef280c7a7a3be8cabd - url: /files/62b720ef280c7a7a3be8cabd_image.png - - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 - official-site: >- - https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy - contact-email: zaphod.beeblebrox@heartofgold.gov - support-phone: 424-242-4242 - answer-to-everything: 42 - release-date: '1979-10-12T00:00:00.000Z' - is-featured: true - brand-color: '#000000' - category: 62b720ef280c7a7a3be8cabf - author: 62b720ef280c7a7a3be8cab0 - tags: - - 62b720ef280c7a7a3be8cab1 - - 62b720ef280c7a7a3be8cab2 - downloadable-asset: - fileId: 62b720ef280c7a7a3be8cab3 - url: /files/62b720ef280c7a7a3be8cab3_document.pdf - response: - body: - id: 42b720ef280c7a7a3be8cabe - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2022-11-29T16:22:43.159Z' - lastUpdated: '2022-11-17T17:19:43.282Z' - createdOn: '2022-11-17T17:11:57.148Z' - isArchived: false - isDraft: false - fieldData: - name: The Hitchhiker's Guide to the Galaxy - slug: hitchhikers-guide-to-the-galaxy - plain-text: Don't Panic. - rich-text: >- -

A Guide to Interstellar Travel

A towel is about the - most massively useful thing an interstellar hitchhiker can - have. Don't forget yours!

- main-image: - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - image-gallery: - - fileId: 62b720ef280c7a7a3be8cabd - url: /files/62b720ef280c7a7a3be8cabd_image.png - - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 - official-site: >- - https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy - contact-email: zaphod.beeblebrox@heartofgold.gov - support-phone: 424-242-4242 - answer-to-everything: 42 - release-date: '1979-10-12T00:00:00.000Z' - is-featured: true - brand-color: '#000000' - category: 62b720ef280c7a7a3be8cabf - author: 62b720ef280c7a7a3be8cab0 - tags: - - 62b720ef280c7a7a3be8cab1 - - 62b720ef280c7a7a3be8cab2 - downloadable-asset: - fileId: 62b720ef280c7a7a3be8cab3 - url: /files/62b720ef280c7a7a3be8cab3_document.pdf - - name: MultipleItems - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - items: - - isArchived: false - isDraft: false - fieldData: - name: Senior Data Analyst - slug: senior-data-analyst - url: https://boards.greenhouse.io/webflow/jobs/26567701 - department: Data - - isArchived: false - isDraft: false - fieldData: - name: Product Manager - slug: product-manager - url: https://boards.greenhouse.io/webflow/jobs/31234567 - department: Product - response: - body: - id: 42b720ef280c7a7a3be8cabe - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2022-11-29T16:22:43.159Z' - lastUpdated: '2022-11-17T17:19:43.282Z' - createdOn: '2022-11-17T17:11:57.148Z' - isArchived: false - isDraft: false - fieldData: - name: The Hitchhiker's Guide to the Galaxy - slug: hitchhikers-guide-to-the-galaxy - plain-text: Don't Panic. - rich-text: >- -

A Guide to Interstellar Travel

A towel is about the - most massively useful thing an interstellar hitchhiker can - have. Don't forget yours!

- main-image: - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - image-gallery: - - fileId: 62b720ef280c7a7a3be8cabd - url: /files/62b720ef280c7a7a3be8cabd_image.png - - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 - official-site: >- - https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy - contact-email: zaphod.beeblebrox@heartofgold.gov - support-phone: 424-242-4242 - answer-to-everything: 42 - release-date: '1979-10-12T00:00:00.000Z' - is-featured: true - brand-color: '#000000' - category: 62b720ef280c7a7a3be8cabf - author: 62b720ef280c7a7a3be8cab0 - tags: - - 62b720ef280c7a7a3be8cab1 - - 62b720ef280c7a7a3be8cab2 - downloadable-asset: - fileId: 62b720ef280c7a7a3be8cab3 - url: /files/62b720ef280c7a7a3be8cab3_document.pdf - delete-items-live: - path: /collections/{collection_id}/items/live - method: DELETE - auth: - - OAuth2: - - cms:write - docs: > - Unpublish up to 100 items from the live site and set the `isDraft` - property to `true`. - - - Items will only be unpublished in the - primary locale unless a `cmsLocaleId` is included in the request. - - - Required scope | `CMS:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: Unpublish Live Collection Items - request: - name: ItemsDeleteItemsLiveRequest - body: - properties: - items: list - content-type: application/json - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - items: - - id: 580e64008c9a982ac9b8b754 - update-items-live: - path: /collections/{collection_id}/items/live - method: PATCH - auth: - - OAuth2: - - cms:write - docs: > - Update a single published item or multiple published items (up to 100) - in a Collection - - - Items will only be updated in the primary - locale, unless a `cmsLocaleId` is included in the request. - - - Required scope | `CMS:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: Update Live Collection Items - request: - name: ItemsUpdateItemsLiveRequest - query-parameters: - skipInvalidFiles: - type: optional - default: true - docs: >- - When true, invalid files are skipped and processing continues. - When false, the entire request fails if any file is invalid. - body: - properties: - items: optional> - content-type: application/json - response: - docs: Request was successful - type: root.CollectionItemListNoPagination - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - name: LocalizedItems - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - response: - body: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - - name: MultipleItems - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - items: - - id: 580e64008c9a982ac9b8b754 - isArchived: false - isDraft: false - fieldData: - name: Senior Data Analyst - slug: senior-data-analyst - url: https://boards.greenhouse.io/webflow/jobs/26567701 - department: Data - - id: 580e64008c9a982ac9b8b754 - isArchived: false - isDraft: false - fieldData: - name: Product Manager - slug: product-manager - url: https://boards.greenhouse.io/webflow/jobs/31234567 - department: Product - response: - body: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - - name: Multiple items updated across multiple locales - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - response: - body: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - lastPublished: '2024-09-27T17:38:29.066Z' - lastUpdated: '2024-09-27T17:38:29.066Z' - createdOn: '2024-09-27T17:38:29.066Z' - isArchived: false - isDraft: false - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - - name: Multiple items updated in a single locale - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - items: - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Ne Paniquez Pas - slug: ne-paniquez-pas - featured: false - - id: 66f6ed9576ddacf3149d5ea6 - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: No Entrar en Pánico - slug: no-entrar-en-panico - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca5 - fieldData: - name: Au Revoir et Merci pour Tous les Poissons - slug: au-revoir-et-merci - featured: false - - id: 66f6ed9576ddacf3149d5eaa - cmsLocaleId: 66f6e966c9e1dc700a857ca4 - fieldData: - name: Hasta Luego y Gracias por Todo el Pescado - slug: hasta-luego-y-gracias - featured: false - response: - body: - items: - - id: 62b720ef280c7a7a3be8cabe - cmsLocaleId: 66f6e966c9e1dc700a857ca3 - lastPublished: '2022-06-30T13:35:20.878Z' - lastUpdated: '2022-06-25T14:51:27.809Z' - createdOn: '2022-06-25T14:51:27.809Z' - isArchived: false - isDraft: false - fieldData: - name: Senior Data Analyst - slug: senior-data-analyst - url: https://boards.greenhouse.io/webflow/jobs/26567701 - department: Data - - id: 62c880ef281c7b7b4cf9dabc - cmsLocaleId: 66f6e966c9e1dc700a857ca3 - lastPublished: '2023-04-15T10:25:18.123Z' - lastUpdated: '2023-04-10T11:45:30.567Z' - createdOn: '2023-04-10T11:45:30.567Z' - isArchived: false - isDraft: false - fieldData: - name: Product Manager - slug: product-manager - url: https://boards.greenhouse.io/webflow/jobs/31234567 - department: Product - create-items: - path: /collections/{collection_id}/items/bulk - method: POST - auth: - - OAuth2: - - cms:write - docs: > - Create an item or multiple items in a CMS Collection across multiple - corresponding locales. - - - - - This endpoint can create up to 100 items in a request. - - If the `cmsLocaleIds` parameter is not included in the request, an item will only be created in the primary locale. - - - - Required scope | `CMS:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: Create Collection Items - request: - name: CreateBulkCollectionItemRequestBody - query-parameters: - skipInvalidFiles: - type: optional - default: true - docs: >- - When true, invalid files are skipped and processing continues. - When false, the entire request fails if any file is invalid. - body: - properties: - cmsLocaleIds: - type: optional> - docs: >- - Array of identifiers for the locales where the item will be - created - isArchived: - type: optional - docs: Indicates whether the item is archived. - default: false - isDraft: - type: optional - docs: Indicates whether the item is in draft state. - default: true - fieldData: CreateBulkCollectionItemRequestBodyFieldData - content-type: application/json - response: - docs: Request was successful - type: root.BulkCollectionItem - status-code: 202 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - name: Create a single item across multiple locales - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - cmsLocaleIds: - - 66f6e966c9e1dc700a857ca3 - - 66f6e966c9e1dc700a857ca4 - - 66f6e966c9e1dc700a857ca5 - isArchived: false - isDraft: false - fieldData: - name: Don’t Panic - slug: dont-panic - response: - body: - id: 580e64008c9a982ac9b8b754 - cmsLocaleIds: - - 653ad57de882f528b32e810e - - 6514390aea353fc691d69827 - - 65143930ea353fc691d69cd8 - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' - - name: Create multiple items across multiple locales - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - cmsLocaleIds: - - 66f6e966c9e1dc700a857ca3 - - 66f6e966c9e1dc700a857ca4 - isArchived: false - isDraft: false - fieldData: - - name: Don’t Panic - slug: dont-panic - - name: So Long and Thanks for All the Fish - slug: so-long-and-thanks - response: - body: - id: 580e64008c9a982ac9b8b754 - cmsLocaleIds: - - 653ad57de882f528b32e810e - - 6514390aea353fc691d69827 - - 65143930ea353fc691d69cd8 - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' - - name: Single item created across multiple locales - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - cmsLocaleIds: - - 66f6e966c9e1dc700a857ca3 - - 66f6e966c9e1dc700a857ca4 - - 66f6e966c9e1dc700a857ca5 - isArchived: false - isDraft: false - fieldData: - name: Don’t Panic - slug: dont-panic - response: - body: - id: 580e64008c9a982ac9b8b754 - cmsLocaleIds: - - 653ad57de882f528b32e810e - - 6514390aea353fc691d69827 - - 65143930ea353fc691d69cd8 - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' - - name: Multiple items created across multiple locales - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - query-parameters: - skipInvalidFiles: true - request: - cmsLocaleIds: - - 66f6e966c9e1dc700a857ca3 - - 66f6e966c9e1dc700a857ca4 - - 66f6e966c9e1dc700a857ca5 - isArchived: false - isDraft: false - fieldData: - name: Don’t Panic - slug: dont-panic - response: - body: - id: 580e64008c9a982ac9b8b754 - cmsLocaleIds: - - 653ad57de882f528b32e810e - - 6514390aea353fc691d69827 - - 65143930ea353fc691d69cd8 - lastPublished: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - createdOn: '2023-03-17T18:47:35.560Z' - isArchived: true - isDraft: true - fieldData: - name: My new item - slug: my-new-item - date: '2022-11-18T00:00:00.000Z' - featured: false - color: '#db4b68' - get-item: - path: /collections/{collection_id}/items/{item_id} - method: GET - auth: - - OAuth2: - - cms:read - docs: | - Get details of a selected Collection Item. - - Required scope | `CMS:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - item_id: - type: string - docs: Unique identifier for an Item - display-name: Get Collection Item - request: - name: ItemsGetItemRequest - query-parameters: - cmsLocaleId: - type: optional - docs: >- - Unique identifier for a CMS Locale. This UID is different from the - Site locale identifier and is listed as `cmsLocaleId` in the Sites - response. To query multiple locales, input a comma separated - string. - response: - docs: Request was successful - type: root.CollectionItem - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - item_id: 580e64008c9a982ac9b8b754 - query-parameters: - cmsLocaleId: cmsLocaleId - response: - body: - id: 42b720ef280c7a7a3be8cabe - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2022-11-29T16:22:43.159Z' - lastUpdated: '2022-11-17T17:19:43.282Z' - createdOn: '2022-11-17T17:11:57.148Z' - isArchived: false - isDraft: false - fieldData: - name: The Hitchhiker's Guide to the Galaxy - slug: hitchhikers-guide-to-the-galaxy - plain-text: Don't Panic. - rich-text: >- -

A Guide to Interstellar Travel

A towel is about the - most massively useful thing an interstellar hitchhiker can - have. Don't forget yours!

- main-image: - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - image-gallery: - - fileId: 62b720ef280c7a7a3be8cabd - url: /files/62b720ef280c7a7a3be8cabd_image.png - - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 - official-site: >- - https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy - contact-email: zaphod.beeblebrox@heartofgold.gov - support-phone: 424-242-4242 - answer-to-everything: 42 - release-date: '1979-10-12T00:00:00.000Z' - is-featured: true - brand-color: '#000000' - category: 62b720ef280c7a7a3be8cabf - author: 62b720ef280c7a7a3be8cab0 - tags: - - 62b720ef280c7a7a3be8cab1 - - 62b720ef280c7a7a3be8cab2 - downloadable-asset: - fileId: 62b720ef280c7a7a3be8cab3 - url: /files/62b720ef280c7a7a3be8cab3_document.pdf - delete-item: - path: /collections/{collection_id}/items/{item_id} - method: DELETE - auth: - - OAuth2: - - cms:write - docs: | - Delete an item from a collection. - - Required scope | `CMS:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - item_id: - type: string - docs: Unique identifier for an Item - display-name: Delete Collection Item - request: - name: ItemsDeleteItemRequest - query-parameters: - cmsLocaleId: - type: optional - docs: >- - Unique identifier for a CMS Locale. This UID is different from the - Site locale identifier and is listed as `cmsLocaleId` in the Sites - response. To query multiple locales, input a comma separated - string. - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - item_id: 580e64008c9a982ac9b8b754 - query-parameters: - cmsLocaleId: cmsLocaleId - update-item: - path: /collections/{collection_id}/items/{item_id} - method: PATCH - auth: - - OAuth2: - - cms:write - docs: | - Update a selected Item in a Collection. - - Required scope | `CMS:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - item_id: - type: string - docs: Unique identifier for an Item - display-name: Update Collection Item - request: - body: root.CollectionItemPatchSingle - query-parameters: - skipInvalidFiles: - type: optional - default: true - docs: >- - When true, invalid files are skipped and processing continues. - When false, the entire request fails if any file is invalid. - name: ItemsUpdateItemRequest - content-type: application/json - response: - docs: Request was successful - type: root.CollectionItem - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - item_id: 580e64008c9a982ac9b8b754 - query-parameters: - skipInvalidFiles: true - request: - isArchived: false - isDraft: false - fieldData: - name: The Hitchhiker's Guide to the Galaxy - slug: hitchhikers-guide-to-the-galaxy - plain-text: Don't Panic. - rich-text: >- -

A Guide to Interstellar Travel

A towel is about the - most massively useful thing an interstellar hitchhiker can have. - Don't forget yours!

- main-image: - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - image-gallery: - - fileId: 62b720ef280c7a7a3be8cabd - url: /files/62b720ef280c7a7a3be8cabd_image.png - - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 - official-site: >- - https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy - contact-email: zaphod.beeblebrox@heartofgold.gov - support-phone: 424-242-4242 - answer-to-everything: 42 - release-date: '1979-10-12T00:00:00.000Z' - is-featured: true - brand-color: '#000000' - category: 62b720ef280c7a7a3be8cabf - author: 62b720ef280c7a7a3be8cab0 - tags: - - 62b720ef280c7a7a3be8cab1 - - 62b720ef280c7a7a3be8cab2 - downloadable-asset: - fileId: 62b720ef280c7a7a3be8cab3 - url: /files/62b720ef280c7a7a3be8cab3_document.pdf - response: - body: - id: 42b720ef280c7a7a3be8cabe - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2022-11-29T16:22:43.159Z' - lastUpdated: '2022-11-17T17:19:43.282Z' - createdOn: '2022-11-17T17:11:57.148Z' - isArchived: false - isDraft: false - fieldData: - name: The Hitchhiker's Guide to the Galaxy - slug: hitchhikers-guide-to-the-galaxy - plain-text: Don't Panic. - rich-text: >- -

A Guide to Interstellar Travel

A towel is about the - most massively useful thing an interstellar hitchhiker can - have. Don't forget yours!

- main-image: - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - image-gallery: - - fileId: 62b720ef280c7a7a3be8cabd - url: /files/62b720ef280c7a7a3be8cabd_image.png - - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 - official-site: >- - https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy - contact-email: zaphod.beeblebrox@heartofgold.gov - support-phone: 424-242-4242 - answer-to-everything: 42 - release-date: '1979-10-12T00:00:00.000Z' - is-featured: true - brand-color: '#000000' - category: 62b720ef280c7a7a3be8cabf - author: 62b720ef280c7a7a3be8cab0 - tags: - - 62b720ef280c7a7a3be8cab1 - - 62b720ef280c7a7a3be8cab2 - downloadable-asset: - fileId: 62b720ef280c7a7a3be8cab3 - url: /files/62b720ef280c7a7a3be8cab3_document.pdf - get-item-live: - path: /collections/{collection_id}/items/{item_id}/live - method: GET - auth: - - OAuth2: - - cms:read - docs: | - Get details of a selected Collection live Item. - - - Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. - - - Required scope | `CMS:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - item_id: - type: string - docs: Unique identifier for an Item - display-name: Get Live Collection Item - request: - name: ItemsGetItemLiveRequest - query-parameters: - cmsLocaleId: - type: optional - docs: >- - Unique identifier for a CMS Locale. This UID is different from the - Site locale identifier and is listed as `cmsLocaleId` in the Sites - response. To query multiple locales, input a comma separated - string. - response: - docs: Request was successful - type: root.CollectionItem - status-code: 200 - url: Data API - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - item_id: 580e64008c9a982ac9b8b754 - query-parameters: - cmsLocaleId: cmsLocaleId - response: - body: - id: 42b720ef280c7a7a3be8cabe - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2022-11-29T16:22:43.159Z' - lastUpdated: '2022-11-17T17:19:43.282Z' - createdOn: '2022-11-17T17:11:57.148Z' - isArchived: false - isDraft: false - fieldData: - name: The Hitchhiker's Guide to the Galaxy - slug: hitchhikers-guide-to-the-galaxy - plain-text: Don't Panic. - rich-text: >- -

A Guide to Interstellar Travel

A towel is about the - most massively useful thing an interstellar hitchhiker can - have. Don't forget yours!

- main-image: - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - image-gallery: - - fileId: 62b720ef280c7a7a3be8cabd - url: /files/62b720ef280c7a7a3be8cabd_image.png - - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 - official-site: >- - https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy - contact-email: zaphod.beeblebrox@heartofgold.gov - support-phone: 424-242-4242 - answer-to-everything: 42 - release-date: '1979-10-12T00:00:00.000Z' - is-featured: true - brand-color: '#000000' - category: 62b720ef280c7a7a3be8cabf - author: 62b720ef280c7a7a3be8cab0 - tags: - - 62b720ef280c7a7a3be8cab1 - - 62b720ef280c7a7a3be8cab2 - downloadable-asset: - fileId: 62b720ef280c7a7a3be8cab3 - url: /files/62b720ef280c7a7a3be8cab3_document.pdf - delete-item-live: - path: /collections/{collection_id}/items/{item_id}/live - method: DELETE - auth: - - OAuth2: - - cms:write - docs: > - Unpublish a live item from the site and set the `isDraft` property to - `true`. - - - For bulk unpublishing, please use [this - endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) - - - Required scope | `CMS:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - item_id: - type: string - docs: Unique identifier for an Item - display-name: Unpublish Live Collection Item - request: - name: ItemsDeleteItemLiveRequest - query-parameters: - cmsLocaleId: - type: optional - docs: >- - Unique identifier for a CMS Locale. This UID is different from the - Site locale identifier and is listed as `cmsLocaleId` in the Sites - response. To query multiple locales, input a comma separated - string. - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - item_id: 580e64008c9a982ac9b8b754 - query-parameters: - cmsLocaleId: cmsLocaleId - update-item-live: - path: /collections/{collection_id}/items/{item_id}/live - method: PATCH - auth: - - OAuth2: - - cms:write - docs: > - Update a selected live Item in a Collection. The updates for this Item - will be published to the live site. - - - Required scope | `CMS:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - item_id: - type: string - docs: Unique identifier for an Item - display-name: Update Live Collection Item - request: - body: root.CollectionItemPatchSingle - query-parameters: - skipInvalidFiles: - type: optional - default: true - docs: >- - When true, invalid files are skipped and processing continues. - When false, the entire request fails if any file is invalid. - name: ItemsUpdateItemLiveRequest - content-type: application/json - response: - docs: Request was successful - type: root.CollectionItem - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - item_id: 580e64008c9a982ac9b8b754 - query-parameters: - skipInvalidFiles: true - request: - isArchived: false - isDraft: false - fieldData: - name: The Hitchhiker's Guide to the Galaxy - slug: hitchhikers-guide-to-the-galaxy - plain-text: Don't Panic. - rich-text: >- -

A Guide to Interstellar Travel

A towel is about the - most massively useful thing an interstellar hitchhiker can have. - Don't forget yours!

- main-image: - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - image-gallery: - - fileId: 62b720ef280c7a7a3be8cabd - url: /files/62b720ef280c7a7a3be8cabd_image.png - - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 - official-site: >- - https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy - contact-email: zaphod.beeblebrox@heartofgold.gov - support-phone: 424-242-4242 - answer-to-everything: 42 - release-date: '1979-10-12T00:00:00.000Z' - is-featured: true - brand-color: '#000000' - category: 62b720ef280c7a7a3be8cabf - author: 62b720ef280c7a7a3be8cab0 - tags: - - 62b720ef280c7a7a3be8cab1 - - 62b720ef280c7a7a3be8cab2 - downloadable-asset: - fileId: 62b720ef280c7a7a3be8cab3 - url: /files/62b720ef280c7a7a3be8cab3_document.pdf - response: - body: - id: 42b720ef280c7a7a3be8cabe - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2022-11-29T16:22:43.159Z' - lastUpdated: '2022-11-17T17:19:43.282Z' - createdOn: '2022-11-17T17:11:57.148Z' - isArchived: false - isDraft: false - fieldData: - name: The Hitchhiker's Guide to the Galaxy - slug: hitchhikers-guide-to-the-galaxy - plain-text: Don't Panic. - rich-text: >- -

A Guide to Interstellar Travel

A towel is about the - most massively useful thing an interstellar hitchhiker can - have. Don't forget yours!

- main-image: - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - image-gallery: - - fileId: 62b720ef280c7a7a3be8cabd - url: /files/62b720ef280c7a7a3be8cabd_image.png - - fileId: 62b720ef280c7a7a3be8cabe - url: /files/62b720ef280c7a7a3be8cabe_image.png - intro-video: https://www.youtube.com/watch?v=aJ83KAggd-4 - official-site: >- - https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy - contact-email: zaphod.beeblebrox@heartofgold.gov - support-phone: 424-242-4242 - answer-to-everything: 42 - release-date: '1979-10-12T00:00:00.000Z' - is-featured: true - brand-color: '#000000' - category: 62b720ef280c7a7a3be8cabf - author: 62b720ef280c7a7a3be8cab0 - tags: - - 62b720ef280c7a7a3be8cab1 - - 62b720ef280c7a7a3be8cab2 - downloadable-asset: - fileId: 62b720ef280c7a7a3be8cab3 - url: /files/62b720ef280c7a7a3be8cab3_document.pdf - publish-item: - path: /collections/{collection_id}/items/publish - method: POST - auth: - - OAuth2: - - cms:write - docs: | - Publish an item or multiple items. - - Required scope | `cms:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - collection_id: - type: string - docs: Unique identifier for a Collection - display-name: Publish Collection Item - request: - body: ItemsPublishItemRequest - content-type: application/json - response: - docs: Request was successful - type: ItemsPublishItemResponse - status-code: 202 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - name: PrimaryLocale - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - itemIds: - - 643fd856d66b6528195ee2ca - - 643fd856d66b6528195ee2cb - - 643fd856d66b6528195ee2cc - response: - body: - publishedItemIds: - - 643fd856d66b6528195ee2ca - - 643fd856d66b6528195ee2cb - errors: - - Staging item ID 643fd856d66b6528195ee2cf not found. - - name: SecondaryLocale - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - items: - - id: 643fd856d66b6528195ee2ca - cmsLocaleIds: - - 653ad57de882f528b32e810e - - id: 643fd856d66b6528195ee2cb - cmsLocaleIds: - - 653ad57de882f528b32e810e - - id: 643fd856d66b6528195ee2cc - cmsLocaleIds: - - 653ad57de882f528b32e810e - response: - body: - publishedItemIds: - - 643fd856d66b6528195ee2ca - - 643fd856d66b6528195ee2cb - errors: - - Staging item ID 643fd856d66b6528195ee2cf not found. - - name: MultipleLocales - path-parameters: - collection_id: 580e63fc8c9a982ac9b8b745 - request: - items: - - id: 643fd856d66b6528195ee2ca - cmsLocaleIds: - - 653ad57de882f528b32e810e - - 6514390aea353fc691d69827 - - 65143930ea353fc691d69cd8 - response: - body: - publishedItemIds: - - 643fd856d66b6528195ee2ca - - 643fd856d66b6528195ee2cb - errors: - - Staging item ID 643fd856d66b6528195ee2cf not found. - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/comments.yml b/.mock/definition/comments.yml deleted file mode 100644 index 573e375..0000000 --- a/.mock/definition/comments.yml +++ /dev/null @@ -1,41 +0,0 @@ -imports: - root: __package__.yml -webhooks: - comment_created: - audiences: [] - method: POST - display-name: New Comment Thread - headers: {} - payload: root.Comment - examples: - - payload: - triggerType: comment_created - payload: - threadId: 679d2ddb5196117ad04d1ffa - commentId: 679d2ddb5196117ad04d1ff8 - type: new_comment - siteId: 679826b3b20b045e176bc4b5 - pageId: 679826b3b20b045e176bc4bc - localeId: 67993753d910db250db64b3e - itemId: 580e64008c9a982ac9b8b754 - breakpoint: main - url: >- - https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ffa&pageId=679826b3b20b045e176bc4bc - content: 'This comment mentions another user [[6287ec36a841b25637c663df]] ' - isResolved: false - author: - userId: 6287ec36a841b25637c663df - email: ford.prefect@heartofgold.spaceship - name: Ford Prefect - mentionedUsers: - - userId: 6287ec36a841b25637c663df - email: arthur.dent@heartofgold.spaceship - name: Arthur Dent - createdOn: '2025-01-31T20:08:59.759Z' - lastUpdated: '2025-01-31T20:08:59.759Z' - docs: | - Information about a new comment thread or reply - - - There may be a delay of up to 5 minutes before new comments appear in the system and trigger the webhook notification. - diff --git a/.mock/definition/components.yml b/.mock/definition/components.yml deleted file mode 100644 index 3370a4f..0000000 --- a/.mock/definition/components.yml +++ /dev/null @@ -1,548 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/components - method: GET - auth: - - OAuth2: - - components:read - docs: | - List of all components for a site. - - Required scope | `components:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Components - request: - name: ComponentsListRequest - query-parameters: - branchId: - type: optional - docs: Scope the operation to work on a specific branch. - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - response: - docs: Request was successful - type: root.ComponentList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - query-parameters: - branchId: 68026fa68ef6dc744c75b833 - limit: 1 - offset: 1 - response: - body: - components: - - id: 6596da6045e56dee495bcbba - name: Primary Button - group: Buttons - description: A default button component that can be used across the site - readonly: true - - id: 658205daa3e8206a523b5ad4 - name: Secondary Button - group: Buttons - description: >- - A secondary button component that can be used across the - site - readonly: true - - id: 6258612d1ee792848f805dcf - name: Card - group: Buttons - description: A button component that can be used across the site - readonly: true - - id: 68a2b1d1ee792848f805dcf - name: Nav - group: Buttons - description: A button component that can be used across the site - readonly: true - pagination: - limit: 20 - offset: 0 - total: 4 - get-content: - path: /sites/{site_id}/components/{component_id}/dom - method: GET - auth: - - OAuth2: - - components:read - docs: > - Get static content from a component definition. This includes text - nodes, image nodes, select nodes, text input nodes, submit button nodes, - and nested component instances. - - To retrieve dynamic content set by component properties, use the [get - component - properties](/data/reference/pages-and-components/components/get-properties) - endpoint. - - - If you do not provide a Locale ID in your request, the response - will return any content that can be localized from the Primary - locale. - - - Required scope | `components:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - component_id: - type: string - docs: Unique identifier for a Component - display-name: Get Component Content - request: - name: ComponentsGetContentRequest - query-parameters: - localeId: - type: optional - docs: > - Unique identifier for a specific Locale. - - - [Lear more about - localization.](/data/v2.0.0/docs/working-with-localization) - branchId: - type: optional - docs: Scope the operation to work on a specific branch. - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - response: - docs: Request was successful - type: root.ComponentDom - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - branchId: 68026fa68ef6dc744c75b833 - limit: 1 - offset: 1 - response: - body: - componentId: 69118560-d0bc-15fc-bbf8-b8fe5f6535b5 - nodes: - - id: id - text: {} - attributes: - key: value - type: text - - id: id - text: {} - attributes: - key: value - type: text - - id: id - image: {} - attributes: - key: value - type: image - - id: id - placeholder: placeholder - attributes: - key: value - type: text-input - - id: id - choices: - - value: value - text: text - attributes: - key: value - type: select - - id: id - value: value - waitingText: waitingText - attributes: - key: value - type: submit-button - - id: id - componentId: componentId - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - type: component-instance - pagination: - limit: 7 - offset: 0 - total: 7 - update-content: - path: /sites/{site_id}/components/{component_id}/dom - method: POST - auth: - - OAuth2: - - components:write - docs: > - This endpoint updates content within a component defintion for - **secondary locales**. It supports updating up to 1000 nodes in a single - request. - - - Before making updates: - - 1. Use the [get component - content](/data/reference/pages-and-components/components/get-content) - endpoint to identify available content nodes and their types. - - 2. If your component definition has a component instance nested within - it, retrieve the nested component instance's properties that you'll - override using the [get component - properties](/data/reference/pages-and-components/components/get-properties) - endpoint. - - 3. DOM elements may include a `data-w-id` attribute. This attribute is - used by Webflow to maintain custom attributes and links across locales. - Always include the original `data-w-id` value in your update requests to - ensure consistent behavior across all locales. - - - - This endpoint is specifically for localizing component definitions. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. - - - - Required scope | `components:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - component_id: - type: string - docs: Unique identifier for a Component - display-name: Update Component Content - request: - name: ComponentDomWrite - query-parameters: - localeId: - type: optional - docs: > - Unique identifier for a specific Locale. - - - [Lear more about - localization.](/data/v2.0.0/docs/working-with-localization) - branchId: - type: optional - docs: Scope the operation to work on a specific branch. - body: - properties: - nodes: - docs: >- - List of DOM Nodes with the new content that will be updated in - each node. - type: list - content-type: application/json - response: - docs: Request was successful - type: ComponentsUpdateContentResponse - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - branchId: 68026fa68ef6dc744c75b833 - request: - nodes: - - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad623 - text:

The Hitchhiker's Guide to the Galaxy

- - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad627 - text: >- -

Don't Panic!

Always know where your towel - is.

- - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad635 - choices: - - value: choice-1 - text: First choice - - value: choice-2 - text: Second choice - - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad642 - placeholder: Enter something here... - - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad671 - value: Submit - waitingText: Submitting... - - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad629 - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - text:

Time is an illusion

- - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f1 - text: Life, the Universe and Everything - response: - body: - errors: - - errors - get-properties: - path: /sites/{site_id}/components/{component_id}/properties - method: GET - auth: - - OAuth2: - - components:read - docs: > - Get the default property values of a component definition. - - - If you do not include a `localeId` in your request, the response - will return any properties that can be localized from the Primary - locale. - - - Required scope | `components:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - component_id: - type: string - docs: Unique identifier for a Component - display-name: Get Component Properties - request: - name: ComponentsGetPropertiesRequest - query-parameters: - localeId: - type: optional - docs: > - Unique identifier for a specific Locale. - - - [Lear more about - localization.](/data/v2.0.0/docs/working-with-localization) - branchId: - type: optional - docs: Scope the operation to work on a specific branch. - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - response: - docs: Request was successful - type: root.ComponentProperties - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - branchId: 68026fa68ef6dc744c75b833 - limit: 1 - offset: 1 - response: - body: - componentId: 658205daa3e8206a523b5ad4 - properties: - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad623 - type: Plain Text - label: Title - text: - text: The Hitchhiker's Guide to the Galaxy - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad627 - type: Rich Text - label: Content - text: - html: >- -

Don't Panic!

Always know where your towel - is.

- pagination: - limit: 2 - offset: 0 - total: 2 - update-properties: - path: /sites/{site_id}/components/{component_id}/properties - method: POST - auth: - - OAuth2: - - components:write - docs: > - Update the default property values of a component definition in a - specificed locale. - - - Before making updates: - - 1. Use the [get component - properties](/data/reference/pages-and-components/components/get-properties) - endpoint to identify properties that can be updated in a secondary - locale. - - 2. Rich Text properties may include a `data-w-id` attribute. This - attribute is used by Webflow to maintain links across locales. Always - include the original `data-w-id` value in your update requests to ensure - consistent behavior across all locales. - - - The request requires a secondary locale ID. If a `localeId` is - missing, the request will not be processed and will result in an - error. - - - Required scope | `components:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - component_id: - type: string - docs: Unique identifier for a Component - display-name: Update Component Properties - request: - name: ComponentPropertiesWrite - query-parameters: - localeId: - type: optional - docs: > - Unique identifier for a specific Locale. - - - [Lear more about - localization.](/data/v2.0.0/docs/working-with-localization) - branchId: - type: optional - docs: Scope the operation to work on a specific branch. - body: - properties: - properties: - docs: >- - A list of component properties to update within the specified - secondary locale. - type: list - content-type: application/json - response: - docs: Request was successful - type: ComponentsUpdatePropertiesResponse - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - component_id: 8505ba55-ef72-629e-f85c-33e4b703d48b - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - branchId: 68026fa68ef6dc744c75b833 - request: - properties: - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad623 - text: The Hitchhiker’s Guide to the Galaxy - - propertyId: a245c12d-995b-55ee-5ec7-aa36a6cad627 - text: >- -

Dont Panic!

Always know where your towel - is.

- response: - body: - errors: - - errors - source: - openapi: ../../../openapi/referenced-specs/v2.yml -types: - ComponentDomWriteNodesItem: - discriminated: false - union: - - type: root.TextNodeWrite - - type: root.ComponentInstanceNodePropertyOverridesWrite - - type: root.Select - - type: root.TextInputNodeWrite - - type: root.SubmitButtonNodeWrite - - type: root.SearchButtonNodeWrite - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - ComponentsUpdateContentResponse: - properties: - errors: - docs: A list of error messages, if any. - type: list - source: - openapi: ../../../openapi/referenced-specs/v2.yml - ComponentPropertiesWritePropertiesItem: - properties: - propertyId: - type: string - docs: The ID of the property. - text: - type: string - docs: > - The new string or HTML value used to update the component property in - the secondary locale. - - - The provided value must be compatible with the type of the component - property. - - - For example, attempting to update a single-line plain-text property - with a multi-line - - value will result in an error. - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - ComponentsUpdatePropertiesResponse: - properties: - errors: - docs: A list of error messages, if any. - type: list - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/ecommerce.yml b/.mock/definition/ecommerce.yml deleted file mode 100644 index 426869f..0000000 --- a/.mock/definition/ecommerce.yml +++ /dev/null @@ -1,45 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - get-settings: - path: /sites/{site_id}/ecommerce/settings - method: GET - auth: - - OAuth2: - - ecommerce:read - docs: | - Retrieve ecommerce settings for a site. - - Required scope | `ecommerce:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Get Ecommerce Settings - response: - docs: Request was successful - type: root.EcommerceSettings - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - siteId: 5eb0b5583bf24e2d3a488969 - createdOn: '2018-10-04T15:21:02Z' - defaultCurrency: USD - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/forms.yml b/.mock/definition/forms.yml deleted file mode 100644 index 08f2926..0000000 --- a/.mock/definition/forms.yml +++ /dev/null @@ -1,399 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/forms - method: GET - auth: - - OAuth2: - - forms:read - docs: | - List forms for a given site. - - Required scope | `forms:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Forms - request: - name: FormsListRequest - query-parameters: - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - response: - docs: Request was successful - type: root.FormList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - query-parameters: - limit: 1 - offset: 1 - response: - body: - forms: - - displayName: Email Form - createdOn: '2016-10-24T19:41:29Z' - lastUpdated: '2016-10-24T19:43:17Z' - fields: - '0': - displayName: Email - placeholder: Enter your email - userVisible: true - '1': - displayName: Email - placeholder: Enter your email - userVisible: true - responseSettings: - redirectUrl: https://example.com - redirectMethod: GET - redirectAction: POST https://example.com - sendEmailConfirmation: true - id: 589a331aa51e760df7ccb89e - siteId: 580e63e98c9a982ac9b8b741 - siteDomainId: 6419db964a9c436a4baf6248 - pageId: 6419db964a9c43f6a3af6348 - pageName: Home - formElementId: 4e038d2c-6a1e-4953-7be9-a59a2b453177 - workspaceId: 580e63fc8c9a982ac9b8b744 - - displayName: Name Form - createdOn: '2016-10-24T19:41:29Z' - lastUpdated: '2016-10-24T19:43:17Z' - fields: - '0': - displayName: Email - placeholder: Enter your email - userVisible: true - responseSettings: - redirectUrl: https://example.com - redirectMethod: GET - redirectAction: POST https://example.com - sendEmailConfirmation: false - id: 580ff8d7ba3e45ba9fe588e9 - siteId: 580e63e98c9a982ac9b8b741 - siteDomainId: 6419db964a9c436a4baf6248 - pageId: 6419db964a9c43f6a3af6348 - pageName: Home - formElementId: 4e038d2c-6a1e-4953-7be9-a59a2b453177 - workspaceId: 580e63fc8c9a982ac9b8b744 - pagination: - limit: 25 - offset: 0 - total: 2 - get: - path: /forms/{form_id} - method: GET - auth: - - OAuth2: - - forms:read - docs: | - Get information about a given form. - - Required scope | `forms:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - form_id: - type: string - docs: Unique identifier for a Form - display-name: Get Form Schema - response: - docs: Request was successful - type: root.Form - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - form_id: 580e63e98c9a982ac9b8b741 - response: - body: - displayName: Email Form - createdOn: '2016-10-24T19:41:29Z' - lastUpdated: '2016-10-24T19:43:17Z' - fields: - 660d5bcc9c0772150459dfb1: - displayName: Name - type: Plain - placeholder: Enter your email - userVisible: true - 589a331aa51e760df7ccb89d: - displayName: Email - type: Email - placeholder: Enter your email - userVisible: true - responseSettings: - redirectUrl: https://example.com - redirectMethod: GET - redirectAction: POST https://example.com - sendEmailConfirmation: true - id: 589a331aa51e760df7ccb89e - siteId: 580e63e98c9a982ac9b8b741 - siteDomainId: 6419db964a9c436a4baf6248 - pageId: 6419db964a9c43f6a3af6348 - pageName: Home - formElementId: 4e038d2c-6a1e-4953-7be9-a59a2b453177 - workspaceId: 580e63fc8c9a982ac9b8b744 - list-submissions: - path: /forms/{form_id}/submissions - method: GET - auth: - - OAuth2: - - forms:read - docs: | - List form submissions for a given form - - - When a form is used in a component definition, each instance of the form is considered a unique form. - - To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. - - - Required scope | `forms:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - form_id: - type: string - docs: Unique identifier for a Form - display-name: List Form Submissions - request: - name: FormsListSubmissionsRequest - query-parameters: - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - response: - docs: Request was successful - type: root.FormSubmissionList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - form_id: 580e63e98c9a982ac9b8b741 - query-parameters: - offset: 1 - limit: 1 - response: - body: - formSubmissions: - - id: 6321ca84df3949bfc6752327 - displayName: Sample Form - siteId: 62749158efef318abc8d5a0f - workspaceId: 62749158efef318abc8d5a0f - dateSubmitted: '2022-09-14T12:35:16Z' - formResponse: - First Name: Arthur - Last Name: Dent - - id: 660d64fabf6e0a0d4edab981 - displayName: Sample Form - siteId: 62749158efef318abc8d5a0f - workspaceId: 62749158efef318abc8d5a0f - dateSubmitted: '2022-09-14T12:35:16Z' - formResponse: - First Name: Ford - Last Name: Prefect - pagination: - limit: 25 - offset: 0 - total: 2 - get-submission: - path: /form_submissions/{form_submission_id} - method: GET - auth: - - OAuth2: - - forms:read - docs: | - Get information about a given form submissio. - - Required scope | `forms:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - form_submission_id: - type: string - docs: Unique identifier for a Form Submission - display-name: Get Form Submission - response: - docs: Request was successful - type: root.FormSubmission - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - form_submission_id: 580e63e98c9a982ac9b8b741 - response: - body: - id: 6321ca84df3949bfc6752327 - displayName: Sample Form - siteId: 62749158efef318abc8d5a0f - workspaceId: 62749158efef318abc8d5a0f - dateSubmitted: '2022-09-14T12:35:16Z' - formResponse: - First Name: Arthur - Last Name: Dent - delete-submission: - path: /form_submissions/{form_submission_id} - method: DELETE - auth: - - OAuth2: - - forms:write - docs: | - Delete a form submission - - - Required scope | `forms:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - form_submission_id: - type: string - docs: Unique identifier for a Form Submission - display-name: Delete Form Submission - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - form_submission_id: 580e63e98c9a982ac9b8b741 - update-submission: - path: /form_submissions/{form_submission_id} - method: PATCH - auth: - - OAuth2: - - forms:write - docs: | - Update hidden fields on a form submission - - Required scope | `forms:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - form_submission_id: - type: string - docs: Unique identifier for a Form Submission - display-name: Modify Form Submission - request: - name: FormsUpdateSubmissionRequest - body: - properties: - formSubmissionData: - type: optional> - docs: >- - An existing **hidden field** defined on the form schema, and the - corresponding value to set - content-type: application/json - response: - docs: Request was successful - type: root.FormSubmission - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - form_submission_id: 580e63e98c9a982ac9b8b741 - request: {} - response: - body: - id: 6321ca84df3949bfc6752327 - displayName: Sample Form - siteId: 62749158efef318abc8d5a0f - workspaceId: 62749158efef318abc8d5a0f - dateSubmitted: '2022-09-14T12:35:16Z' - formResponse: - First Name: Arthur - Last Name: Dent - source: - openapi: ../../../openapi/referenced-specs/v2.yml - display-name: Forms -docs: Forms are forms that are created on your Webflow site. -webhooks: - form_submission: - audiences: [] - method: POST - display-name: Form Submission - headers: {} - payload: root.FormSubmissionTrigger - examples: - - payload: - triggerType: form_submission - payload: - name: Contact Us - siteId: 65427cf400e02b306eaa049c - data: - First Name: Zaphod - Last Name: Beeblebrox - email: zaphod@heartofgold.ai - Phone Number: 15550000000 - schema: - - fieldName: First Name - fieldType: FormTextInput - fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c4 - - fieldName: Last Name - fieldType: FormTextInput - fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c5 - - fieldName: email - fieldType: FormTextInput - fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c6 - - fieldName: Phone Number - fieldType: FormTextInput - fieldElementId: 285042f7-d554-dc7f-102c-aa10d6a2d2c7 - submittedAt: '2022-09-14T12:35:16.117Z' - id: 6321ca84df3949bfc6752327 - formId: 65429eadebe8a9f3a30f62d0 - formElementId: 4e038d2c-6a1e-4953-7be9-a59a2b453177 - docs: Information about a form that was subitted diff --git a/.mock/definition/inventory.yml b/.mock/definition/inventory.yml deleted file mode 100644 index 139fa04..0000000 --- a/.mock/definition/inventory.yml +++ /dev/null @@ -1,152 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /collections/{sku_collection_id}/items/{sku_id}/inventory - method: GET - auth: - - OAuth2: - - ecommerce:read - docs: | - List the current inventory levels for a particular SKU item. - - Required scope | `ecommerce:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - sku_collection_id: - type: string - docs: >- - Unique identifier for a SKU collection. Use the List Collections API - to find this ID. - sku_id: - type: string - docs: Unique identifier for a SKU - display-name: List Inventory - response: - docs: Request was successful - type: root.InventoryItem - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - sku_collection_id: 6377a7c4b7a79608c34a46f7 - sku_id: 5e8518516e147040726cc415 - response: - body: - id: 5bfedb42bab0ad90fa7dad39 - quantity: 100 - inventoryType: finite - update: - path: /collections/{sku_collection_id}/items/{sku_id}/inventory - method: PATCH - auth: - - OAuth2: - - ecommerce:write - docs: > - Updates the current inventory levels for a particular SKU item. - - - Updates may be given in one or two methods, absolutely or - incrementally. - - - Absolute updates are done by setting `quantity` directly. - - - Incremental updates are by specifying the inventory delta in - `updateQuantity` which is then added to the `quantity` stored on the - server. - - - Required scope | `ecommerce:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - sku_collection_id: - type: string - docs: >- - Unique identifier for a SKU collection. Use the List Collections API - to find this ID. - sku_id: - type: string - docs: Unique identifier for a SKU - display-name: Update Item Inventory - request: - name: InventoryUpdateRequest - body: - properties: - inventoryType: - type: InventoryUpdateRequestInventoryType - docs: infinite or finite - updateQuantity: - type: optional - docs: Adds this quantity to currently store quantity. Can be negative. - quantity: - type: optional - docs: Immediately sets quantity to this value. - content-type: application/json - response: - docs: Request was successful - type: root.InventoryItem - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - sku_collection_id: 6377a7c4b7a79608c34a46f7 - sku_id: 5e8518516e147040726cc415 - request: - inventoryType: infinite - response: - body: - id: 5bfedb42bab0ad90fa7dad39 - quantity: 100 - inventoryType: finite - source: - openapi: ../../../openapi/referenced-specs/v2.yml - display-name: Inventory -docs: Inventory is the stock of e-commerce items in your Webflow site. -types: - InventoryUpdateRequestInventoryType: - enum: - - infinite - - finite - docs: infinite or finite - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - EcommInventoryChangedPayload: - properties: - triggerType: optional> - payload: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml -webhooks: - ecomm_inventory_changed: - audiences: [] - method: POST - display-name: Updated eComm Inventory - headers: {} - payload: EcommInventoryChangedPayload - examples: - - name: WebhookInventoryChanged - payload: - triggerType: ecomm_inventory_changed - payload: - \$ref: ./schemas/inventory.yml#/InventoryItem/example - docs: Information about updated ecommerce inventory values diff --git a/.mock/definition/items.yml b/.mock/definition/items.yml deleted file mode 100644 index 634f1f7..0000000 --- a/.mock/definition/items.yml +++ /dev/null @@ -1,112 +0,0 @@ -imports: - root: __package__.yml -webhooks: - collection_item_created: - audiences: [] - method: POST - display-name: Collection Item Created - headers: {} - payload: root.CollectionItemCreated - examples: - - payload: - triggerType: collection_item_created - payload: - id: 580e64008c9a982ac9b8b754 - workspaceId: 625860a7a6c16d624927122f - siteId: 65427cf400e02b306eaa049c - collectionId: 664243617fcc8b464b23c4ee - lastPublished: '2023-03-17T18:47:35Z' - lastUpdated: '2023-03-17T18:47:35Z' - createdOn: '2023-03-17T18:47:35Z' - isArchived: false - isDraft: false - fieldData: - name: Pan-Galactic Gargle Blaster - slug: pan-galactic-gargle-blaster - docs: Information about a new collection item - collection_item_changed: - audiences: [] - method: POST - display-name: Collection Item Updated - headers: {} - payload: root.CollectionItemChanged - examples: - - payload: - triggerType: collection_item_changed - payload: - id: id - workspaceId: workspaceId - siteId: siteId - collectionId: collectionId - fieldData: - name: name - slug: slug - docs: Information about an updated collection item - collection_item_deleted: - audiences: [] - method: POST - display-name: Collection Item Deleted - headers: {} - payload: root.CollectionItemRemoved - examples: - - payload: - triggerType: collection_item_deleted - payload: - id: 66424365e972c886137a1cf1 - siteId: 65427cf400e02b306eaa049c - workspaceId: 625860a7a6c16d624927122f - collectionId: 664243617fcc8b464b23c4ee - cmsLocaleId: 681442a144bb80bd00480fda - lastUpdated: '2025-05-28T04:44:33Z' - createdOn: '2025-05-28T04:27:12Z' - isArchived: false - isDraft: false - fieldData: - name: Earth - slug: earth - description: Mostly harmless - color: '#0000FF' - type: planet - galaxy: Milky Way - docs: Information about a deleted collection item - collection_item_published: - audiences: [] - method: POST - display-name: Collection Item Published - headers: {} - payload: root.CollectionItemPublished - examples: - - payload: - triggerType: collection_item_published - payload: - id: 6321ca84df3949bfc6752327 - siteId: 65427cf400e02b306eaa049c - workspaceId: 625860a7a6c16d624927122f - collectionId: 664243617fcc8b464b23c4ee - cmsLocaleId: 681442a144bb80bd00480fda - docs: Information about a collection item that was published - collection_item_unpublished: - audiences: [] - method: POST - display-name: Collection Item Unpublished - headers: {} - payload: root.CollectionItemUnpublished - examples: - - payload: - triggerType: collection_item_unpublished - payload: - id: 66424365e972c886137a1cf1 - siteId: 65427cf400e02b306eaa049c - workspaceId: 625860a7a6c16d624927122f - collectionId: 664243617fcc8b464b23c4ee - cmsLocaleId: 681442a144bb80bd00480fda - lastUpdated: '2025-05-28T04:44:33Z' - createdOn: '2025-05-28T04:27:12Z' - isArchived: false - isDraft: false - fieldData: - name: Anna Gunn - slug: anna-gunn - _locale: 681442a144bb80bd00480fda - _noSearch: false - docs: Information about a collection item that was removed from the live site diff --git a/.mock/definition/orders.yml b/.mock/definition/orders.yml deleted file mode 100644 index 1f9711e..0000000 --- a/.mock/definition/orders.yml +++ /dev/null @@ -1,1971 +0,0 @@ -types: - OrdersListRequestStatus: - enum: - - pending - - refunded - - value: dispute-lost - name: DisputeLost - - fulfilled - - disputed - - unfulfilled - source: - openapi: ../../../openapi/referenced-specs/v2.yml - OrdersRefundRequestReason: - enum: - - duplicate - - fraudulent - - requested - docs: The reason for the refund - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/orders - method: GET - auth: - - OAuth2: - - ecommerce:read - docs: | - List all orders created for a given site. - - Required scope | `ecommerce:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Orders - request: - name: OrdersListRequest - query-parameters: - status: - type: optional - docs: Filter the orders by status - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - response: - docs: Request was successful - type: root.OrderList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - query-parameters: - status: pending - offset: 1 - limit: 1 - response: - body: - orders: - - orderId: 7c1-9fd - status: unfulfilled - comment: >- - Customer requested gift wrapping and a personalized note - saying: Happy Birthday, Ford! 🎉 Please ensure the item is - packed with extra bubble wrap for safe transit. - orderComment: >- - Please gift wrap with a personal note saying "Happy - Birthday, Ford! 🎉 - acceptedOn: '2024-04-10T13:16:21Z' - fulfilledOn: '2018-12-03T22:06:15Z' - refundedOn: '2018-12-03T22:06:15Z' - disputedOn: '2018-12-03T22:06:15Z' - disputeUpdatedOn: '2018-12-03T22:06:15Z' - disputeLastStatus: warning_needs_response - customerPaid: - unit: USD - value: '5892' - string: \$ 211.55 USD - netAmount: - unit: USD - value: '5892' - string: \$ 200.89 USD - applicationFee: - unit: USD - value: '5892' - string: \$ 4.23 USD - allAddresses: - - type: billing - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - - type: shipping - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingAddress: - type: shipping - japanType: kanji - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - billingAddress: - type: billing - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingProvider: Shipping Company, Co. - shippingTracking: tr00000000002 - shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000002 - customerInfo: - fullName: Arthur Dent - email: arthur.dent@example.com - purchasedItems: - - count: 2 - rowTotal: - unit: USD - value: '5892' - string: \$ 111.22 USD - productId: 66072fb61b89448912e26791 - productName: Luxurious Fresh Ball - productSlug: luxurious-fresh-ball - variantId: 66072fb71b89448912e2683f - variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' - variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic - variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 55.61 USD - weight: 11 - width: 82 - height: 70 - length: 9 - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 83.09 USD - productId: 66072fb61b89448912e2678b - productName: Incredible Bronze Towels - productSlug: incredible-bronze-towels - variantId: 66072fb71b89448912e2681e - variantName: >- - Incredible Bronze Towels Sleek: Frozen, Incredible: - Metal - variantSlug: incredible-bronze-towels-sleek-frozen-incredible-metal - variantSKU: incredible-bronze-towels-sleek-frozen-incredible-metal - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 83.09 USD - weight: 5 - width: 19 - height: 72 - length: 18 - purchasedItemsCount: 3 - stripeDetails: - subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn - paymentMethod: pm_1P410gJYFi4lcbXWbeKghqjK - paymentIntentId: pi_3P410iJYFi4lcbXW0EKKgcVg - customerId: cus_Ptod8KJBiiPgnH - chargeId: ch_3P410iJYFi4lcbXW0DxUkzCH - refundReason: requested_by_customer - stripeCard: - last4: '4242' - brand: Visa - ownerName: Arthur Dent - expires: - year: 2025 - month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq - customData: - - key: value - metadata: - isBuyNow: false - isCustomerDeleted: false - isShippingRequired: false - hasDownloads: false - paymentProcessor: stripe - totals: - extras: - - type: tax - name: State Taxes - description: CA Taxes (6.25%) - price: - unit: USD - value: '5892' - string: \$3.44 - downloadFiles: - - id: 5e9a5eba75e0ac242e1b6f64 - name: The modern web design process - Webflow Ebook.pdf - url: >- - https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa - - orderId: fc7-128 - status: refunded - comment: Example comment to myself - orderComment: '' - acceptedOn: '2024-03-29T21:29:21Z' - fulfilledOn: '2018-12-03T22:06:15Z' - refundedOn: '2024-04-08T18:25:04Z' - disputedOn: '2018-12-03T22:06:15Z' - disputeUpdatedOn: '2018-12-03T22:06:15Z' - disputeLastStatus: warning_needs_response - customerPaid: - unit: USD - value: '5892' - string: \$ 118.73 USD - netAmount: - unit: USD - value: '5892' - string: \$ 112.62 USD - applicationFee: - unit: USD - value: '5892' - string: \$ 2.37 USD - allAddresses: - - type: billing - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - - type: shipping - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingAddress: - type: shipping - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - billingAddress: - type: billing - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingProvider: Shipping Company, Co. - shippingTracking: tr00000000001 - shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 - customerInfo: - fullName: Arthur Dent - email: arthur.dent@example.com - purchasedItems: - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 55.61 USD - productId: 66072fb61b89448912e26791 - productName: Luxurious Fresh Ball - productSlug: luxurious-fresh-ball - variantId: 66072fb71b89448912e2683f - variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' - variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic - variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 55.61 USD - weight: 11 - width: 82 - height: 70 - length: 9 - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 53.44 USD - productId: 66072fb61b89448912e26799 - productName: Recycled Steel Gloves - productSlug: recycled-steel-gloves - variantId: 66072fb91b89448912e26ab9 - variantName: >- - Recycled Steel Gloves Electronic: Granite, Handcrafted: - grey - variantSlug: >- - recycled-steel-gloves-electronic-granite-handcrafted-grey - variantSKU: >- - recycled-steel-gloves-electronic-granite-handcrafted-grey - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 53.44 USD - weight: 38 - width: 76 - height: 85 - length: 40 - purchasedItemsCount: 2 - stripeDetails: - subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn - paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j - paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft - customerId: cus_PpRsNHwWdUoRKR - chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 - refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk - refundReason: fraudulent - stripeCard: - last4: '4242' - brand: Visa - ownerName: Arthur Dent - expires: - year: 2024 - month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq - customData: - - key: value - metadata: - isBuyNow: false - isCustomerDeleted: false - isShippingRequired: true - hasDownloads: false - paymentProcessor: stripe - totals: - subtotal: - unit: USD - value: '5892' - string: \$ 109.05 USD - extras: - - type: tax - name: State Taxes - description: NY Taxes (4.00%) - price: - unit: USD - value: '5892' - string: \$ 4.36 USD - - type: tax - name: City Taxes - description: NEW YORK Taxes (4.88%) - price: - unit: USD - value: '5892' - string: \$ 5.32 USD - - type: shipping - name: Flat - description: '' - price: - unit: USD - value: '5892' - string: \$ 0.00 USD - total: - unit: USD - value: '5892' - string: \$ 118.73 USD - downloadFiles: - - id: 5e9a5eba75e0ac242e1b6f64 - name: New product guide - url: >- - https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa - pagination: - limit: 100 - offset: 0 - total: 2 - get: - path: /sites/{site_id}/orders/{order_id} - method: GET - auth: - - OAuth2: - - ecommerce:read - docs: | - Retrieve a single product by its ID. All of its SKUs will also be - retrieved. - - Required scope | `ecommerce:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - order_id: - type: string - docs: Unique identifier for an Order - display-name: Get Order - response: - docs: Request was successful - type: root.Order - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - order_id: 5e8518516e147040726cc415 - response: - body: - orderId: fc7-128 - status: refunded - comment: >- - Customer requested gift wrapping and a personalized note saying: - Happy Birthday, Ford! 🎉 Please ensure the item is packed with - extra bubble wrap for safe transit. - orderComment: >- - Please gift wrap with a personal note saying "Happy Birthday, - Ford! 🎉 - acceptedOn: '2024-03-29T21:29:21Z' - fulfilledOn: '2024-03-29T21:29:21Z' - refundedOn: '2024-04-08T18:25:04Z' - disputedOn: '2024-03-29T21:29:21Z' - disputeUpdatedOn: '2024-03-29T21:29:21Z' - disputeLastStatus: charge_refunded - customerPaid: - unit: USD - value: '5892' - string: \$ 118.73 USD - netAmount: - unit: USD - value: '5892' - string: \$ 112.62 USD - applicationFee: - unit: USD - value: '5892' - string: \$ 2.37 USD - allAddresses: - - type: billing - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - - type: shipping - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingAddress: - type: shipping - japanType: kanji - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - billingAddress: - type: billing - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingProvider: Shipping Company, Co. - shippingTracking: tr00000000001 - shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 - customerInfo: - fullName: Arthur Dent - email: arthur.dent@example.com - purchasedItems: - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 55.61 USD - productId: 66072fb61b89448912e26791 - productName: Luxurious Fresh Ball - productSlug: luxurious-fresh-ball - variantId: 66072fb71b89448912e2683f - variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' - variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic - variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 55.61 USD - weight: 11 - width: 82 - height: 70 - length: 9 - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 53.44 USD - productId: 66072fb61b89448912e26799 - productName: Recycled Steel Gloves - productSlug: recycled-steel-gloves - variantId: 66072fb91b89448912e26ab9 - variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' - variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 53.44 USD - weight: 38 - width: 76 - height: 85 - length: 40 - purchasedItemsCount: 2 - stripeDetails: - subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn - paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j - paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft - customerId: cus_PpRsNHwWdUoRKR - chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 - disputeId: disputeId - refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk - refundReason: fraudulent - stripeCard: - last4: '4242' - brand: Visa - ownerName: Arthur Dent - expires: - year: 2024 - month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq - customData: - - key: value - metadata: - isBuyNow: false - isCustomerDeleted: false - isShippingRequired: true - hasDownloads: false - paymentProcessor: stripe - totals: - subtotal: - unit: USD - value: '5892' - string: \$ 109.05 USD - extras: - - type: tax - name: State Taxes - description: NY Taxes (4.00%) - price: - unit: USD - value: '5892' - string: \$ 4.36 USD - - type: tax - name: City Taxes - description: NEW YORK Taxes (4.88%) - price: - unit: USD - value: '5892' - string: \$ 5.32 USD - - type: shipping - name: Flat - description: '' - price: - unit: USD - value: '5892' - string: \$ 0.00 USD - total: - unit: USD - value: '5892' - string: \$ 118.73 USD - downloadFiles: - - id: 5e9a5eba75e0ac242e1b6f64 - name: New product guide - url: >- - https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa - update: - path: /sites/{site_id}/orders/{order_id} - method: PATCH - auth: - - OAuth2: - - ecommerce:write - docs: | - This API lets you update the fields, `comment`, `shippingProvider`, - and/or `shippingTracking` for a given order. All three fields can be - updated simultaneously or independently. - - Required scope | `ecommerce:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - order_id: - type: string - docs: Unique identifier for an Order - display-name: Update Order - request: - name: OrdersUpdateRequest - body: - properties: - comment: - type: optional - docs: Arbitrary data for your records - shippingProvider: - type: optional - docs: Company or method used to ship order - shippingTracking: - type: optional - docs: Tracking number for order shipment - shippingTrackingURL: - type: optional - docs: URL to track order shipment - content-type: application/json - response: - docs: Request was successful - type: root.Order - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - order_id: 5e8518516e147040726cc415 - request: {} - response: - body: - orderId: fc7-128 - status: refunded - comment: >- - Customer requested gift wrapping and a personalized note saying: - Happy Birthday, Ford! 🎉 Please ensure the item is packed with - extra bubble wrap for safe transit. - orderComment: >- - Please gift wrap with a personal note saying "Happy Birthday, - Ford! 🎉 - acceptedOn: '2024-03-29T21:29:21Z' - fulfilledOn: '2024-03-29T21:29:21Z' - refundedOn: '2024-04-08T18:25:04Z' - disputedOn: '2024-03-29T21:29:21Z' - disputeUpdatedOn: '2024-03-29T21:29:21Z' - disputeLastStatus: charge_refunded - customerPaid: - unit: USD - value: '5892' - string: \$ 118.73 USD - netAmount: - unit: USD - value: '5892' - string: \$ 112.62 USD - applicationFee: - unit: USD - value: '5892' - string: \$ 2.37 USD - allAddresses: - - type: billing - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - - type: shipping - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingAddress: - type: shipping - japanType: kanji - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - billingAddress: - type: billing - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingProvider: Shipping Company, Co. - shippingTracking: tr00000000001 - shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 - customerInfo: - fullName: Arthur Dent - email: arthur.dent@example.com - purchasedItems: - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 55.61 USD - productId: 66072fb61b89448912e26791 - productName: Luxurious Fresh Ball - productSlug: luxurious-fresh-ball - variantId: 66072fb71b89448912e2683f - variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' - variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic - variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 55.61 USD - weight: 11 - width: 82 - height: 70 - length: 9 - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 53.44 USD - productId: 66072fb61b89448912e26799 - productName: Recycled Steel Gloves - productSlug: recycled-steel-gloves - variantId: 66072fb91b89448912e26ab9 - variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' - variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 53.44 USD - weight: 38 - width: 76 - height: 85 - length: 40 - purchasedItemsCount: 2 - stripeDetails: - subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn - paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j - paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft - customerId: cus_PpRsNHwWdUoRKR - chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 - disputeId: disputeId - refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk - refundReason: fraudulent - stripeCard: - last4: '4242' - brand: Visa - ownerName: Arthur Dent - expires: - year: 2024 - month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq - customData: - - key: value - metadata: - isBuyNow: false - isCustomerDeleted: false - isShippingRequired: true - hasDownloads: false - paymentProcessor: stripe - totals: - subtotal: - unit: USD - value: '5892' - string: \$ 109.05 USD - extras: - - type: tax - name: State Taxes - description: NY Taxes (4.00%) - price: - unit: USD - value: '5892' - string: \$ 4.36 USD - - type: tax - name: City Taxes - description: NEW YORK Taxes (4.88%) - price: - unit: USD - value: '5892' - string: \$ 5.32 USD - - type: shipping - name: Flat - description: '' - price: - unit: USD - value: '5892' - string: \$ 0.00 USD - total: - unit: USD - value: '5892' - string: \$ 118.73 USD - downloadFiles: - - id: 5e9a5eba75e0ac242e1b6f64 - name: New product guide - url: >- - https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa - update-fulfill: - path: /sites/{site_id}/orders/{order_id}/fulfill - method: POST - auth: - - OAuth2: - - ecommerce:write - docs: | - Updates an order's status to fulfilled - - Required scope | `ecommerce:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - order_id: - type: string - docs: Unique identifier for an Order - display-name: Fulfill Order - request: - name: OrdersUpdateFulfillRequest - body: - properties: - sendOrderFulfilledEmail: - type: optional - docs: Whether or not the Order Fulfilled email should be sent - default: false - content-type: application/json - response: - docs: Request was successful - type: root.Order - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - order_id: 5e8518516e147040726cc415 - request: {} - response: - body: - orderId: fc7-128 - status: refunded - comment: >- - Customer requested gift wrapping and a personalized note saying: - Happy Birthday, Ford! 🎉 Please ensure the item is packed with - extra bubble wrap for safe transit. - orderComment: >- - Please gift wrap with a personal note saying "Happy Birthday, - Ford! 🎉 - acceptedOn: '2024-03-29T21:29:21Z' - fulfilledOn: '2024-03-29T21:29:21Z' - refundedOn: '2024-04-08T18:25:04Z' - disputedOn: '2024-03-29T21:29:21Z' - disputeUpdatedOn: '2024-03-29T21:29:21Z' - disputeLastStatus: charge_refunded - customerPaid: - unit: USD - value: '5892' - string: \$ 118.73 USD - netAmount: - unit: USD - value: '5892' - string: \$ 112.62 USD - applicationFee: - unit: USD - value: '5892' - string: \$ 2.37 USD - allAddresses: - - type: billing - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - - type: shipping - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingAddress: - type: shipping - japanType: kanji - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - billingAddress: - type: billing - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingProvider: Shipping Company, Co. - shippingTracking: tr00000000001 - shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 - customerInfo: - fullName: Arthur Dent - email: arthur.dent@example.com - purchasedItems: - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 55.61 USD - productId: 66072fb61b89448912e26791 - productName: Luxurious Fresh Ball - productSlug: luxurious-fresh-ball - variantId: 66072fb71b89448912e2683f - variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' - variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic - variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 55.61 USD - weight: 11 - width: 82 - height: 70 - length: 9 - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 53.44 USD - productId: 66072fb61b89448912e26799 - productName: Recycled Steel Gloves - productSlug: recycled-steel-gloves - variantId: 66072fb91b89448912e26ab9 - variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' - variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 53.44 USD - weight: 38 - width: 76 - height: 85 - length: 40 - purchasedItemsCount: 2 - stripeDetails: - subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn - paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j - paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft - customerId: cus_PpRsNHwWdUoRKR - chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 - disputeId: disputeId - refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk - refundReason: fraudulent - stripeCard: - last4: '4242' - brand: Visa - ownerName: Arthur Dent - expires: - year: 2024 - month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq - customData: - - key: value - metadata: - isBuyNow: false - isCustomerDeleted: false - isShippingRequired: true - hasDownloads: false - paymentProcessor: stripe - totals: - subtotal: - unit: USD - value: '5892' - string: \$ 109.05 USD - extras: - - type: tax - name: State Taxes - description: NY Taxes (4.00%) - price: - unit: USD - value: '5892' - string: \$ 4.36 USD - - type: tax - name: City Taxes - description: NEW YORK Taxes (4.88%) - price: - unit: USD - value: '5892' - string: \$ 5.32 USD - - type: shipping - name: Flat - description: '' - price: - unit: USD - value: '5892' - string: \$ 0.00 USD - total: - unit: USD - value: '5892' - string: \$ 118.73 USD - downloadFiles: - - id: 5e9a5eba75e0ac242e1b6f64 - name: New product guide - url: >- - https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa - update-unfulfill: - path: /sites/{site_id}/orders/{order_id}/unfulfill - method: POST - auth: - - OAuth2: - - ecommerce:write - docs: | - Updates an order's status to unfulfilled - - Required scope | `ecommerce:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - order_id: - type: string - docs: Unique identifier for an Order - display-name: Unfulfill Order - response: - docs: Request was successful - type: root.Order - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - order_id: 5e8518516e147040726cc415 - response: - body: - orderId: fc7-128 - status: refunded - comment: >- - Customer requested gift wrapping and a personalized note saying: - Happy Birthday, Ford! 🎉 Please ensure the item is packed with - extra bubble wrap for safe transit. - orderComment: >- - Please gift wrap with a personal note saying "Happy Birthday, - Ford! 🎉 - acceptedOn: '2024-03-29T21:29:21Z' - fulfilledOn: '2024-03-29T21:29:21Z' - refundedOn: '2024-04-08T18:25:04Z' - disputedOn: '2024-03-29T21:29:21Z' - disputeUpdatedOn: '2024-03-29T21:29:21Z' - disputeLastStatus: charge_refunded - customerPaid: - unit: USD - value: '5892' - string: \$ 118.73 USD - netAmount: - unit: USD - value: '5892' - string: \$ 112.62 USD - applicationFee: - unit: USD - value: '5892' - string: \$ 2.37 USD - allAddresses: - - type: billing - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - - type: shipping - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingAddress: - type: shipping - japanType: kanji - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - billingAddress: - type: billing - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingProvider: Shipping Company, Co. - shippingTracking: tr00000000001 - shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 - customerInfo: - fullName: Arthur Dent - email: arthur.dent@example.com - purchasedItems: - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 55.61 USD - productId: 66072fb61b89448912e26791 - productName: Luxurious Fresh Ball - productSlug: luxurious-fresh-ball - variantId: 66072fb71b89448912e2683f - variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' - variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic - variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 55.61 USD - weight: 11 - width: 82 - height: 70 - length: 9 - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 53.44 USD - productId: 66072fb61b89448912e26799 - productName: Recycled Steel Gloves - productSlug: recycled-steel-gloves - variantId: 66072fb91b89448912e26ab9 - variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' - variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 53.44 USD - weight: 38 - width: 76 - height: 85 - length: 40 - purchasedItemsCount: 2 - stripeDetails: - subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn - paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j - paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft - customerId: cus_PpRsNHwWdUoRKR - chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 - disputeId: disputeId - refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk - refundReason: fraudulent - stripeCard: - last4: '4242' - brand: Visa - ownerName: Arthur Dent - expires: - year: 2024 - month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq - customData: - - key: value - metadata: - isBuyNow: false - isCustomerDeleted: false - isShippingRequired: true - hasDownloads: false - paymentProcessor: stripe - totals: - subtotal: - unit: USD - value: '5892' - string: \$ 109.05 USD - extras: - - type: tax - name: State Taxes - description: NY Taxes (4.00%) - price: - unit: USD - value: '5892' - string: \$ 4.36 USD - - type: tax - name: City Taxes - description: NEW YORK Taxes (4.88%) - price: - unit: USD - value: '5892' - string: \$ 5.32 USD - - type: shipping - name: Flat - description: '' - price: - unit: USD - value: '5892' - string: \$ 0.00 USD - total: - unit: USD - value: '5892' - string: \$ 118.73 USD - downloadFiles: - - id: 5e9a5eba75e0ac242e1b6f64 - name: New product guide - url: >- - https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa - refund: - path: /sites/{site_id}/orders/{order_id}/refund - method: POST - auth: - - OAuth2: - - ecommerce:write - docs: | - This API will reverse a Stripe charge and refund an order back to a - customer. It will also set the order's status to `refunded`. - - Required scope | `ecommerce:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - order_id: - type: string - docs: Unique identifier for an Order - display-name: Refund Order - request: - name: OrdersRefundRequest - body: - properties: - reason: - type: optional - docs: The reason for the refund - content-type: application/json - response: - docs: Request was successful - type: root.Order - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - order_id: 5e8518516e147040726cc415 - request: {} - response: - body: - orderId: fc7-128 - status: refunded - comment: >- - Customer requested gift wrapping and a personalized note saying: - Happy Birthday, Ford! 🎉 Please ensure the item is packed with - extra bubble wrap for safe transit. - orderComment: >- - Please gift wrap with a personal note saying "Happy Birthday, - Ford! 🎉 - acceptedOn: '2024-03-29T21:29:21Z' - fulfilledOn: '2024-03-29T21:29:21Z' - refundedOn: '2024-04-08T18:25:04Z' - disputedOn: '2024-03-29T21:29:21Z' - disputeUpdatedOn: '2024-03-29T21:29:21Z' - disputeLastStatus: charge_refunded - customerPaid: - unit: USD - value: '5892' - string: \$ 118.73 USD - netAmount: - unit: USD - value: '5892' - string: \$ 112.62 USD - applicationFee: - unit: USD - value: '5892' - string: \$ 2.37 USD - allAddresses: - - type: billing - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - - type: shipping - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingAddress: - type: shipping - japanType: kanji - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - billingAddress: - type: billing - japanType: kana - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingProvider: Shipping Company, Co. - shippingTracking: tr00000000001 - shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 - customerInfo: - fullName: Arthur Dent - email: arthur.dent@example.com - purchasedItems: - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 55.61 USD - productId: 66072fb61b89448912e26791 - productName: Luxurious Fresh Ball - productSlug: luxurious-fresh-ball - variantId: 66072fb71b89448912e2683f - variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' - variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic - variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 55.61 USD - weight: 11 - width: 82 - height: 70 - length: 9 - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 53.44 USD - productId: 66072fb61b89448912e26799 - productName: Recycled Steel Gloves - productSlug: recycled-steel-gloves - variantId: 66072fb91b89448912e26ab9 - variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' - variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 53.44 USD - weight: 38 - width: 76 - height: 85 - length: 40 - purchasedItemsCount: 2 - stripeDetails: - subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn - paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j - paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft - customerId: cus_PpRsNHwWdUoRKR - chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 - disputeId: disputeId - refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk - refundReason: fraudulent - stripeCard: - last4: '4242' - brand: Visa - ownerName: Arthur Dent - expires: - year: 2024 - month: 4 - paypalDetails: - orderId: 1a2b3c4d5e6f7g8h9i0j - payerId: 9k8j7i6h5g4f3e2d1c0b - captureId: qwe123rty456uio789p - refundId: abcde12345fghij67890 - refundReason: Customer requested refund - disputeId: zxcvbnm987poiuytrewq - customData: - - key: value - metadata: - isBuyNow: false - isCustomerDeleted: false - isShippingRequired: true - hasDownloads: false - paymentProcessor: stripe - totals: - subtotal: - unit: USD - value: '5892' - string: \$ 109.05 USD - extras: - - type: tax - name: State Taxes - description: NY Taxes (4.00%) - price: - unit: USD - value: '5892' - string: \$ 4.36 USD - - type: tax - name: City Taxes - description: NEW YORK Taxes (4.88%) - price: - unit: USD - value: '5892' - string: \$ 5.32 USD - - type: shipping - name: Flat - description: '' - price: - unit: USD - value: '5892' - string: \$ 0.00 USD - total: - unit: USD - value: '5892' - string: \$ 118.73 USD - downloadFiles: - - id: 5e9a5eba75e0ac242e1b6f64 - name: New product guide - url: >- - https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa - source: - openapi: ../../../openapi/referenced-specs/v2.yml - display-name: Orders -docs: Orders are the orders for your Webflow site. -webhooks: - ecomm_new_order: - audiences: [] - method: POST - display-name: New eComm Order - headers: {} - payload: root.NewOrder - examples: - - payload: - triggerType: ecomm_new_order - payload: - orderId: fc7-128 - status: unfulfilled - comment: >- - Customer requested gift wrapping and a personalized note saying: - Happy Birthday, Ford! 🎉 Please ensure the item is packed with - extra bubble wrap for safe transit. - orderComment: >- - Please gift wrap with a personal note saying "Happy Birthday, - Ford! 🎉 - acceptedOn: '2024-03-29T21:29:21Z' - fulfilledOn: '2018-12-03T22:06:15Z' - refundedOn: '2018-12-03T22:06:15Z' - disputedOn: '2018-12-03T22:06:15Z' - disputeUpdatedOn: '2018-12-03T22:06:15Z' - customerPaid: - unit: USD - value: '5892' - string: \$ 118.73 USD - netAmount: - unit: USD - value: '5892' - string: \$ 112.62 USD - applicationFee: - unit: USD - value: '5892' - string: \$ 2.37 USD - allAddresses: - - type: billing - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - - type: shipping - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingAddress: - type: shipping - japanType: kanji - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - billingAddress: - type: billing - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingProvider: Shipping Company, Co. - shippingTracking: tr00000000001 - shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 - customerInfo: - fullName: Arthur Dent - email: arthur.dent@example.com - purchasedItems: - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 55.61 USD - productId: 66072fb61b89448912e26791 - productName: Luxurious Fresh Ball - productSlug: luxurious-fresh-ball - variantId: 66072fb71b89448912e2683f - variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' - variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic - variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 55.61 USD - weight: 11 - width: 82 - height: 70 - length: 9 - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 53.44 USD - productId: 66072fb61b89448912e26799 - productName: Recycled Steel Gloves - productSlug: recycled-steel-gloves - variantId: 66072fb91b89448912e26ab9 - variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' - variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 53.44 USD - weight: 38 - width: 76 - height: 85 - length: 40 - purchasedItemsCount: 2 - stripeDetails: - subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn - paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j - paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft - customerId: cus_PpRsNHwWdUoRKR - chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 - refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk - refundReason: fraudulent - stripeCard: - last4: '4242' - brand: Visa - ownerName: Arthur Dent - expires: - year: 2024 - month: 4 - customData: - - key: value - metadata: - isBuyNow: false - isCustomerDeleted: false - isShippingRequired: true - hasDownloads: false - paymentProcessor: stripe - totals: - subtotal: - unit: USD - value: '5892' - string: \$ 109.05 USD - extras: - - type: tax - name: State Taxes - description: NY Taxes (4.00%) - price: - unit: USD - value: '5892' - string: \$ 4.36 USD - - type: tax - name: City Taxes - description: NEW YORK Taxes (4.88%) - price: - unit: USD - value: '5892' - string: \$ 5.32 USD - - type: shipping - name: Flat - description: '' - price: - unit: USD - value: '5892' - string: \$ 0.00 USD - total: - unit: USD - value: '5892' - string: \$ 118.73 USD - downloadFiles: - - id: 5e9a5eba75e0ac242e1b6f64 - name: New product guide - url: >- - https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa - docs: Information about a new ecommerce order - ecomm_order_changed: - audiences: [] - method: POST - display-name: Updated eComm Order - headers: {} - payload: root.UpdatedOrder - examples: - - payload: - triggerType: ecomm_order_changed - payload: - orderId: fc7-128 - status: refunded - comment: >- - Customer requested gift wrapping and a personalized note saying: - Happy Birthday, Ford! 🎉 Please ensure the item is packed with - extra bubble wrap for safe transit. - orderComment: >- - Please gift wrap with a personal note saying "Happy Birthday, - Ford! 🎉 - acceptedOn: '2024-03-29T21:29:21Z' - fulfilledOn: '2024-03-29T21:29:21Z' - refundedOn: '2024-04-08T18:25:04Z' - disputedOn: '2024-03-29T21:29:21Z' - disputeUpdatedOn: '2024-03-29T21:29:21Z' - disputeLastStatus: charge_refunded - customerPaid: - unit: USD - value: '5892' - string: \$ 118.73 USD - netAmount: - unit: USD - value: '5892' - string: \$ 112.62 USD - applicationFee: - unit: USD - value: '5892' - string: \$ 2.37 USD - allAddresses: - - type: billing - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - - type: shipping - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingAddress: - type: shipping - japanType: kanji - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - billingAddress: - type: billing - addressee: Arthur Dent - line1: 20 W 34th St - line2: Empire State Building - city: New York - state: New York - country: US - postalCode: '10118' - shippingProvider: Shipping Company, Co. - shippingTracking: tr00000000001 - shippingTrackingURL: https://www.shippingcompany.com/tracking/tr00000000001 - customerInfo: - fullName: Arthur Dent - email: arthur.dent@example.com - purchasedItems: - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 55.61 USD - productId: 66072fb61b89448912e26791 - productName: Luxurious Fresh Ball - productSlug: luxurious-fresh-ball - variantId: 66072fb71b89448912e2683f - variantName: 'Luxurious Fresh Ball Generic: Bronze, Practical: Plastic' - variantSlug: luxurious-fresh-ball-generic-bronze-practical-plastic - variantSKU: luxurious-fresh-ball-generic-bronze-practical-plastic - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 55.61 USD - weight: 11 - width: 82 - height: 70 - length: 9 - - count: 1 - rowTotal: - unit: USD - value: '5892' - string: \$ 53.44 USD - productId: 66072fb61b89448912e26799 - productName: Recycled Steel Gloves - productSlug: recycled-steel-gloves - variantId: 66072fb91b89448912e26ab9 - variantName: 'Recycled Steel Gloves Electronic: Granite, Handcrafted: grey' - variantSlug: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantSKU: recycled-steel-gloves-electronic-granite-handcrafted-grey - variantImage: - url: >- - https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg - variantPrice: - unit: USD - value: '5892' - string: \$ 53.44 USD - weight: 38 - width: 76 - height: 85 - length: 40 - purchasedItemsCount: 2 - stripeDetails: - subscriptionId: sub_1J6xwG2eZvKYlo2CXu9Zt0Tn - paymentMethod: pm_1OzmzBJYFi4lcbXWHKNdXU7j - paymentIntentId: pi_3OzmzDJYFi4lcbXW1hTBW6ft - customerId: cus_PpRsNHwWdUoRKR - chargeId: ch_3OzmzDJYFi4lcbXW1ndkkrH2 - refundId: re_3OzmzDJYFi4lcbXW1kFAmlBk - refundReason: fraudulent - stripeCard: - last4: '4242' - brand: Visa - ownerName: Arthur Dent - expires: - year: 2024 - month: 4 - customData: - - key: value - metadata: - isBuyNow: false - isCustomerDeleted: false - isShippingRequired: true - hasDownloads: false - paymentProcessor: stripe - totals: - subtotal: - unit: USD - value: '5892' - string: \$ 109.05 USD - extras: - - type: tax - name: State Taxes - description: NY Taxes (4.00%) - price: - unit: USD - value: '5892' - string: \$ 4.36 USD - - type: tax - name: City Taxes - description: NEW YORK Taxes (4.88%) - price: - unit: USD - value: '5892' - string: \$ 5.32 USD - - type: shipping - name: Flat - description: '' - price: - unit: USD - value: '5892' - string: \$ 0.00 USD - total: - unit: USD - value: '5892' - string: \$ 118.73 USD - downloadFiles: - - id: 5e9a5eba75e0ac242e1b6f64 - name: New product guide - url: >- - https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa - docs: Information about an updated ecommerce order diff --git a/.mock/definition/pages.yml b/.mock/definition/pages.yml deleted file mode 100644 index 12d954e..0000000 --- a/.mock/definition/pages.yml +++ /dev/null @@ -1,611 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/pages - method: GET - auth: - - OAuth2: - - page:read - docs: | - List of all pages for a site. - - Required scope | `pages:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Pages - request: - name: PagesListRequest - query-parameters: - localeId: - type: optional - docs: > - Unique identifier for a specific Locale. - - - [Lear more about - localization.](/data/v2.0.0/docs/working-with-localization) - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - response: - docs: Request was successful - type: root.PageList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - limit: 1 - offset: 1 - response: - body: - pages: - - id: 6596da6045e56dee495bcbba - siteId: 6258612d1ee792848f805dcf - title: Guide to the Galaxy - slug: guide-to-the-galaxy - parentId: 6419db964a9c435aa3af6251 - collectionId: 6390c49774a71f12831a08e3 - createdOn: '2024-03-11T10:42:00Z' - lastUpdated: '2024-03-11T10:42:42Z' - archived: false - draft: false - canBranch: false - isBranch: true - branchId: 68026fa68ef6dc744c75b833 - seo: - title: The Ultimate Hitchhiker's Guide to the Galaxy - description: >- - Everything you need to know about the galaxy, from - avoiding Vogon poetry to the importance of towels. - openGraph: - title: Explore the Cosmos with The Ultimate Guide - titleCopied: false - description: >- - Dive deep into the mysteries of the universe with your - guide to everything galactic. - descriptionCopied: false - localeId: 653fd9af6a07fc9cfd7a5e57 - publishedPath: /en-us/guide-to-the-galaxy - - id: 6596da6045e56dee495bcbad - siteId: 6258612d1ee792848f805dcf - title: Towel Day Celebrations - slug: towel-day - parentId: 6419db964a9c435aa3af6251 - collectionId: 6390c49774a71f12831a08e3 - createdOn: '2024-05-25T09:00:00Z' - lastUpdated: '2024-05-25T09:42:00Z' - archived: false - draft: false - canBranch: true - isBranch: false - branchId: 68026fa68ef6dc744c75b833 - seo: - title: Celebrate Towel Day - The Hitchhiker's Guide to the Galaxy - description: >- - A guide to celebrating Towel Day, in honor of the most - massively useful thing an interstellar hitchhiker can - have. - openGraph: - title: Towel Day - Don't Panic - titleCopied: false - description: >- - Join the galaxy in celebrating Towel Day, the day - dedicated to carrying towels everywhere in memory of - Douglas Adams. - descriptionCopied: false - localeId: 653fd9af6a07fc9cfd7a5e57 - publishedPath: /en-us/towel-day - pagination: - limit: 20 - offset: 0 - total: 2 - get-metadata: - path: /pages/{page_id} - method: GET - auth: - - OAuth2: - - page:read - docs: | - Get metadata information for a single page. - - Required scope | `pages:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - page_id: - type: string - docs: Unique identifier for a Page - display-name: Get Page Metadata - request: - name: PagesGetMetadataRequest - query-parameters: - localeId: - type: optional - docs: > - Unique identifier for a specific Locale. - - - [Lear more about - localization.](/data/v2.0.0/docs/working-with-localization) - response: - docs: Request was successful - type: root.Page - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - page_id: 63c720f9347c2139b248e552 - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - response: - body: - id: 6596da6045e56dee495bcbba - siteId: 6258612d1ee792848f805dcf - title: Guide to the Galaxy - slug: guide-to-the-galaxy - parentId: 6419db964a9c435aa3af6251 - collectionId: 6390c49774a71f12831a08e3 - createdOn: '2024-03-11T10:42:00Z' - lastUpdated: '2024-03-11T10:42:42Z' - archived: false - draft: false - canBranch: false - isBranch: true - branchId: 68026fa68ef6dc744c75b833 - seo: - title: The Ultimate Hitchhiker's Guide to the Galaxy - description: >- - Everything you need to know about the galaxy, from avoiding - Vogon poetry to the importance of towels. - openGraph: - title: Explore the Cosmos with The Ultimate Guide - titleCopied: false - description: >- - Dive deep into the mysteries of the universe with your guide - to everything galactic. - descriptionCopied: false - localeId: 653fd9af6a07fc9cfd7a5e57 - publishedPath: /en-us/guide-to-the-galaxy - update-page-settings: - path: /pages/{page_id} - method: PUT - auth: - - OAuth2: - - page:write - docs: | - Update Page-level metadata, including SEO and Open Graph fields. - - Required scope | `pages:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - page_id: - type: string - docs: Unique identifier for a Page - display-name: Update Page Metadata - request: - name: PageMetadataWrite - query-parameters: - localeId: - type: optional - docs: > - Unique identifier for a specific Locale. - - - [Lear more about - localization.](/data/v2.0.0/docs/working-with-localization) - body: - properties: - title: - type: optional - docs: Title for the page - slug: - type: optional - docs: > - Slug for the page. - - - - **Note:** Updating slugs in secondary locales is only supported - in Advanced and - Enterprise localization add-on plans. - seo: - type: optional - docs: SEO-related fields for the Page - openGraph: - type: optional - docs: Open Graph fields for the Page - content-type: application/json - response: - docs: Request was successful - type: root.Page - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - page_id: 63c720f9347c2139b248e552 - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - request: - title: Guide to the Galaxy - slug: guide-to-the-galaxy - seo: - title: The Ultimate Hitchhiker's Guide to the Galaxy - description: >- - Everything you need to know about the galaxy, from avoiding - Vogon poetry to the importance of towels. - openGraph: - title: Explore the Cosmos with The Ultimate Guide - titleCopied: false - description: >- - Dive deep into the mysteries of the universe with your guide to - everything galactic. - descriptionCopied: false - response: - body: - id: 6596da6045e56dee495bcbba - siteId: 6258612d1ee792848f805dcf - title: Guide to the Galaxy - slug: guide-to-the-galaxy - parentId: 6419db964a9c435aa3af6251 - collectionId: 6390c49774a71f12831a08e3 - createdOn: '2024-03-11T10:42:00Z' - lastUpdated: '2024-03-11T10:42:42Z' - archived: false - draft: false - canBranch: false - isBranch: true - branchId: 68026fa68ef6dc744c75b833 - seo: - title: The Ultimate Hitchhiker's Guide to the Galaxy - description: >- - Everything you need to know about the galaxy, from avoiding - Vogon poetry to the importance of towels. - openGraph: - title: Explore the Cosmos with The Ultimate Guide - titleCopied: false - description: >- - Dive deep into the mysteries of the universe with your guide - to everything galactic. - descriptionCopied: false - localeId: 653fd9af6a07fc9cfd7a5e57 - publishedPath: /en-us/guide-to-the-galaxy - get-content: - path: /pages/{page_id}/dom - method: GET - auth: - - OAuth2: - - page:read - docs: | - Get text and component instance content from a static page. - - Localization - - Required scope | `pages:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - page_id: - type: string - docs: Unique identifier for a Page - display-name: Get Page Content - request: - name: PagesGetContentRequest - query-parameters: - localeId: - type: optional - docs: > - Unique identifier for a specific Locale. - - - [Lear more about - localization.](/data/v2.0.0/docs/working-with-localization) - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - response: - docs: Request was successful - type: root.Dom - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - page_id: 63c720f9347c2139b248e552 - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - limit: 1 - offset: 1 - response: - body: - pageId: 658205daa3e8206a523b5ad4 - branchId: 68026fa68ef6dc744c75b833 - nodes: - - id: id - text: {} - attributes: - key: value - type: text - - id: id - text: {} - attributes: - key: value - type: text - - id: id - image: {} - attributes: - key: value - type: image - - id: id - choices: - - value: value - text: text - attributes: - key: value - type: select - - id: id - placeholder: placeholder - attributes: - key: value - type: text-input - - id: id - text: {} - attributes: - key: value - type: text - - id: id - componentId: componentId - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - type: component-instance - pagination: - limit: 4 - offset: 0 - total: 4 - lastUpdated: '2016-10-24T19:42:38Z' - update-static-content: - path: /pages/{page_id}/dom - method: POST - auth: - - OAuth2: - - page:write - docs: > - This endpoint updates content on a static page in **secondary locales**. - It supports updating up to 1000 nodes in a single request. - - - Before making updates: - - 1. Use the [get page - content](/data/reference/pages-and-components/pages/get-content) - endpoint to identify available content nodes and their types. - - 2. If the page has component instances, retrieve the component's - properties that you'll override using the [get component - properties](/data/reference/pages-and-components/components/get-properties) - endpoint. - - 3. DOM elements may include a `data-w-id` attribute. This attribute is - used by Webflow to maintain custom attributes and links across locales. - Always include the original `data-w-id` value in your update requests to - ensure consistent behavior across all locales. - - - - This endpoint is specifically for localized pages. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. - - - - Required scope | `pages:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - page_id: - type: string - docs: Unique identifier for a Page - display-name: Update Page Content - request: - name: PageDomWrite - query-parameters: - localeId: - type: string - docs: The locale identifier. - body: - properties: - nodes: - docs: >- - List of DOM Nodes with the new content that will be updated in - each node. - type: list - content-type: application/json - response: - docs: Request was successful - type: UpdateStaticContentResponse - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - page_id: 63c720f9347c2139b248e552 - query-parameters: - localeId: localeId - request: - nodes: - - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad623 - text:

The Hitchhiker's Guide to the Galaxy

- - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad627 - text: >- -

Don't Panic!

Always know where your towel - is.

- - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad635 - choices: - - value: choice-1 - text: First choice - - value: choice-2 - text: Second choice - - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad642 - placeholder: Enter something here... - - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad671 - value: Submit - waitingText: Submitting... - - nodeId: a245c12d-995b-55ee-5ec7-aa36a6cad629 - propertyOverrides: - - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f0 - text:

Time is an illusion

- - propertyId: 7dd14c08-2e96-8d3d-2b19-b5c03642a0f1 - text: Life, the Universe and Everything - response: - body: - errors: - - errors - source: - openapi: ../../../openapi/referenced-specs/v2.yml - display-name: Pages -docs: Pages are the pages in your Webflow site. -types: - PageMetadataWriteSeo: - docs: SEO-related fields for the Page - properties: - title: - type: optional - docs: The Page title shown in search engine results - description: - type: optional - docs: The Page description shown in search engine results - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - PageMetadataWriteOpenGraph: - docs: Open Graph fields for the Page - properties: - title: - type: optional - docs: The title supplied to Open Graph annotations - titleCopied: - type: optional - docs: Indicates the Open Graph title was copied from the SEO title - description: - type: optional - docs: The description supplied to Open Graph annotations - descriptionCopied: - type: optional - docs: >- - Indicates the Open Graph description was copied from the SEO - description - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - PageDomWriteNodesItem: - discriminated: false - union: - - type: root.TextNodeWrite - - type: root.ComponentInstanceNodePropertyOverridesWrite - - type: root.Select - - type: root.TextInputNodeWrite - - type: root.SubmitButtonNodeWrite - - type: root.SearchButtonNodeWrite - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - UpdateStaticContentResponse: - properties: - errors: - docs: A list of error messages, if any. - type: list - source: - openapi: ../../../openapi/referenced-specs/v2.yml -webhooks: - page_created: - audiences: [] - method: POST - display-name: Page Created - headers: {} - payload: root.PageCreatedWebhook - examples: - - payload: - triggerType: page_created - payload: - siteId: 65427cf400e02b306eaa049c - pageId: 66a3cfb276641574f5d58311 - pageTitle: Heart of Gold Specs - createdOn: '2024-07-26T16:32:50Z' - publishedPath: /blog/earth - docs: Information about a new pages - page_metadata_updated: - audiences: [] - method: POST - display-name: Page Metadata Updated - headers: {} - payload: root.PageMetadataUpdatedWebhook - examples: - - payload: - triggerType: page_metadata_updated - payload: - siteId: 65427cf400e02b306eaa049c - pageId: 66a3cfb276641574f5d58311 - pageTitle: Heart of Gold Specs - lastUpdated: '2024-07-26T16:32:50Z' - publishedPath: /blog/earth - docs: Information about a page's updated metadata and/or settings - page_deleted: - audiences: [] - method: POST - display-name: Page Deleted - headers: {} - payload: root.PageDeletedWebhook - examples: - - payload: - triggerType: page_deleted - payload: - siteId: 65427cf400e02b306eaa049c - pageId: 66a3cfb276641574f5d58311 - pageTitle: Heart of Gold Specs - deletedOn: '2024-07-26T16:32:50Z' - publishedPath: /blog/earth - docs: Information about a page that was deleted diff --git a/.mock/definition/pages/scripts.yml b/.mock/definition/pages/scripts.yml deleted file mode 100644 index 59bc96a..0000000 --- a/.mock/definition/pages/scripts.yml +++ /dev/null @@ -1,155 +0,0 @@ -imports: - root: ../__package__.yml -service: - auth: false - base-path: '' - endpoints: - get-custom-code: - path: /pages/{page_id}/custom_code - method: GET - auth: - - OAuth2: - - custom_code:read - docs: | - Get all scripts applied to a page. - - Required scope | `custom_code:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - page_id: - type: string - docs: Unique identifier for a Page - display-name: Get Custom Code - response: - docs: Request was successful - type: root.ScriptApplyList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - page_id: 63c720f9347c2139b248e552 - response: - body: - scripts: - - id: id - location: header - version: version - attributes: - key: value - lastUpdated: lastUpdated - createdOn: createdOn - upsert-custom-code: - path: /pages/{page_id}/custom_code - method: PUT - auth: - - OAuth2: - - custom_code:write - docs: > - Apply registered scripts to a page. If you have multiple scripts your - App needs to apply or maintain on a page, ensure they are always - included in the request body for this endpoint. To remove individual - scripts, simply call this endpoint without the script in the request - body. - - - - To apply a script to a page, the script must first be registered to a Site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. - - - - Required scope | `custom_code:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - page_id: - type: string - docs: Unique identifier for a Page - display-name: Add/Update Custom Code - request: - body: root.ScriptApplyList - content-type: application/json - response: - docs: Request was successful - type: root.ScriptApplyList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - page_id: 63c720f9347c2139b248e552 - request: - scripts: - - id: cms_slider - location: header - version: 1.0.0 - attributes: - my-attribute: some-value - - id: alert - location: header - version: 0.0.1 - response: - body: - scripts: - - id: cms_slider - location: header - version: 1.0.0 - attributes: - my-attribute: some-value - - id: alert - location: header - version: 0.0.1 - attributes: - key: value - lastUpdated: '2022-10-26T00:28:54.191Z' - createdOn: '2022-10-26T00:28:54.191Z' - delete-custom-code: - path: /pages/{page_id}/custom_code - method: DELETE - auth: - - OAuth2: - - custom_code:write - docs: > - Remove all scripts from a page applied by the App. This endpoint will - not remove scripts from the site's registered scripts. - - - To remove individual scripts applied by the App, use the [Add/Update - Custom - Code](/data/reference/custom-code/custom-code-pages/upsert-custom-code) - endpoint. - - - Access to this endpoint requires a bearer token obtained from an - [OAuth Code Grant Flow](/data/reference/oauth-app). - - - Required scope | `custom_code:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - page_id: - type: string - docs: Unique identifier for a Page - display-name: Delete Custom Code - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - page_id: 63c720f9347c2139b248e552 - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/products.yml b/.mock/definition/products.yml deleted file mode 100644 index 9474978..0000000 --- a/.mock/definition/products.yml +++ /dev/null @@ -1,642 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/products - method: GET - auth: - - OAuth2: - - ecommerce:read - docs: > - Retrieve all products for a site. - - - Use `limit` and `offset` to page through all products with subsequent - requests. All SKUs for each product - - will also be fetched and returned. The `limit`, `offset` and `total` - values represent Products only and do not include any SKUs. - - - Required scope | `ecommerce:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Products & SKUs - request: - name: ProductsListRequest - query-parameters: - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - response: - docs: Request was successful - type: root.ProductAndSkUsList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - query-parameters: - offset: 1 - limit: 1 - response: - body: - items: - - product: - id: 660eb7a486d1d6e0412292d7 - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2024-04-04T14:24:19Z' - lastUpdated: '2024-04-04T14:30:19Z' - createdOn: '2024-04-04T14:22:28Z' - isArchived: false - isDraft: false - fieldData: - name: T-Shirt - slug: t-shirt - description: A plain cotton t-shirt. - shippable: true - sku-properties: - - id: Color - name: Color - enum: - - id: royal-blue - name: Royal Blue - slug: royal-blue - skus: - - id: 66072fb71b89448912e2681c - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35Z' - lastUpdated: '2023-03-17T18:47:35Z' - createdOn: '2023-03-17T18:47:35Z' - fieldData: - sku-values: - color: blue - size: small - name: Colorful T-shirt - Default - slug: colorful-t-shirt-default - price: - value: 2499 - unit: USD - currency: USD - main-image: https://www.example.com/image.jpg - sku: '1234567890' - sku-properties: - - id: Color - name: Color - enum: - - id: royal-blue - name: Royal Blue - slug: royal-blue - pagination: - limit: 100 - offset: 0 - total: 100 - create: - path: /sites/{site_id}/products - method: POST - auth: - - OAuth2: - - ecommerce:write - docs: > - Create a new ecommerce product and defaultSKU. A product, at minimum, - must have a single SKU. - - - To create a product with multiple SKUs: - - First, create a list of `sku-properties`, also known as [product options](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). For example, a T-shirt product may have a "color" `sku-property`, with a list of enum values: red, yellow, and blue, another `sku-property` may be "size", with a list of enum values: small, medium, and large. - - Once, a product is created with a list of `sku-properties`, Webflow will create a **default SKU**, which is always a combination of the first `enum` values of each `sku-property`. (e.g. Small - Red - T-Shirt) - - After creation, you can create additional SKUs for the product, using the [Create SKUs endpoint.](/data/reference/ecommerce/products/create-sku) - - Upon creation, the default product type will be `Advanced`, which - ensures all Product and SKU fields will be shown to users in the - Designer. - - - Required scope | `ecommerce:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Create Product & SKU - request: - name: ProductSkuCreate - body: - properties: - publishStatus: optional - product: ProductSkuCreateProduct - sku: ProductSkuCreateSku - content-type: application/json - response: - docs: Request was successful - type: root.ProductAndSkUs - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - publishStatus: staging - product: - fieldData: - name: Colorful T-shirt - slug: colorful-t-shirt - description: >- - Our best-selling t-shirt available in multiple colors and - sizes - sku-properties: - - id: color - name: Color - enum: - - id: red - name: Red - slug: red - - id: yellow - name: Yellow - slug: yellow - - id: blue - name: Blue - slug: blue - - id: size - name: Size - enum: - - id: small - name: Small - slug: small - - id: medium - name: Medium - slug: medium - - id: large - name: Large - slug: large - sku: - fieldData: - name: Colorful T-shirt - Red Small - slug: colorful-t-shirt-red-small - price: - value: 2499 - unit: USD - currency: USD - main-image: >- - https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987 - response: - body: - product: - id: 660eb7a486d1d6e0412292d7 - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2024-04-04T14:24:19Z' - lastUpdated: '2024-04-04T14:30:19Z' - createdOn: '2024-04-04T14:22:28Z' - isArchived: false - isDraft: false - fieldData: - name: T-Shirt - slug: t-shirt - description: A plain cotton t-shirt. - shippable: true - sku-properties: - - id: Color - name: Color - enum: - - id: royal-blue - name: Royal Blue - slug: royal-blue - category: - - category - tax-category: standard-taxable - default-sku: default-sku - ec-product-type: ff42fee0113744f693a764e3431a9cc2 - skus: - - id: 66072fb71b89448912e2681c - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35Z' - lastUpdated: '2023-03-17T18:47:35Z' - createdOn: '2023-03-17T18:47:35Z' - fieldData: - sku-values: - color: blue - size: small - name: Colorful T-shirt - Default - slug: colorful-t-shirt-default - price: - value: 2499 - unit: USD - currency: USD - main-image: https://www.example.com/image.jpg - sku: '1234567890' - sku-properties: - - id: Color - name: Color - enum: - - id: royal-blue - name: Royal Blue - slug: royal-blue - get: - path: /sites/{site_id}/products/{product_id} - method: GET - auth: - - OAuth2: - - ecommerce:read - docs: | - Retrieve a single product by its ID. All of its SKUs will also be - retrieved. - - Required scope | `ecommerce:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - product_id: - type: string - docs: Unique identifier for a Product - display-name: Get Product and SKUs - response: - docs: Request was successful - type: root.ProductAndSkUs - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - product_id: 580e63fc8c9a982ac9b8b745 - response: - body: - product: - id: 660eb7a486d1d6e0412292d7 - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2024-04-04T14:24:19Z' - lastUpdated: '2024-04-04T14:30:19Z' - createdOn: '2024-04-04T14:22:28Z' - isArchived: false - isDraft: false - fieldData: - name: T-Shirt - slug: t-shirt - description: A plain cotton t-shirt. - shippable: true - sku-properties: - - id: Color - name: Color - enum: - - id: royal-blue - name: Royal Blue - slug: royal-blue - category: - - category - tax-category: standard-taxable - default-sku: default-sku - ec-product-type: ff42fee0113744f693a764e3431a9cc2 - skus: - - id: 66072fb71b89448912e2681c - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35Z' - lastUpdated: '2023-03-17T18:47:35Z' - createdOn: '2023-03-17T18:47:35Z' - fieldData: - sku-values: - color: blue - size: small - name: Colorful T-shirt - Default - slug: colorful-t-shirt-default - price: - value: 2499 - unit: USD - currency: USD - main-image: https://www.example.com/image.jpg - sku: '1234567890' - sku-properties: - - id: Color - name: Color - enum: - - id: royal-blue - name: Royal Blue - slug: royal-blue - update: - path: /sites/{site_id}/products/{product_id} - method: PATCH - auth: - - OAuth2: - - ecommerce:write - docs: > - Update an existing Product. - - - Updating an existing Product will set the product type to `Advanced`, - which ensures all Product and SKU fields will be shown to users in the - Designer. - - - Required scope | `ecommerce:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - product_id: - type: string - docs: Unique identifier for a Product - display-name: Update Product - request: - name: ProductSkuUpdate - body: - properties: - publishStatus: optional - product: optional - sku: optional - content-type: application/json - response: - docs: Request was successful - type: root.Product - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - product_id: 580e63fc8c9a982ac9b8b745 - request: {} - response: - body: - id: 660eb7a486d1d6e0412292d7 - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2024-04-04T14:24:19Z' - lastUpdated: '2024-04-04T14:30:19Z' - createdOn: '2024-04-04T14:22:28Z' - isArchived: false - isDraft: false - fieldData: - name: T-Shirt - slug: t-shirt - description: A plain cotton t-shirt. - shippable: true - sku-properties: - - id: Color - name: Color - enum: - - id: royal-blue - name: Royal Blue - slug: royal-blue - category: - - category - tax-category: standard-taxable - default-sku: default-sku - ec-product-type: ff42fee0113744f693a764e3431a9cc2 - create-sku: - path: /sites/{site_id}/products/{product_id}/skus - method: POST - auth: - - OAuth2: - - ecommerce:write - docs: > - Create additional SKUs to manage every [option and variant of your - Product.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants) - - - Creating SKUs through the API will set the product type to `Advanced`, - which ensures all Product and SKU fields will be shown to users in the - Designer. - - - Required scope | `ecommerce:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - product_id: - type: string - docs: Unique identifier for a Product - display-name: Create SKUs - request: - name: ProductsCreateSkuRequest - body: - properties: - publishStatus: optional - skus: - docs: An array of the SKU data your are adding - type: list - content-type: application/json - response: - docs: Request was successful - type: ProductsCreateSkuResponse - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - product_id: 580e63fc8c9a982ac9b8b745 - request: - skus: - - id: 66072fb71b89448912e2681c - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35Z' - lastUpdated: '2023-03-17T18:47:35Z' - createdOn: '2023-03-17T18:47:35Z' - fieldData: - name: Colorful T-shirt - Default - slug: colorful-t-shirt-default - price: - value: 2499 - unit: USD - currency: USD - response: - body: - skus: - - id: 66072fb71b89448912e2681c - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35Z' - lastUpdated: '2023-03-17T18:47:35Z' - createdOn: '2023-03-17T18:47:35Z' - fieldData: - sku-values: - color: blue - size: small - name: Colorful T-shirt - Default - slug: colorful-t-shirt-default - price: - value: 2499 - unit: USD - currency: USD - main-image: https://www.example.com/image.jpg - sku: '1234567890' - sku-properties: - - id: Color - name: Color - enum: - - id: royal-blue - name: Royal Blue - slug: royal-blue - update-sku: - path: /sites/{site_id}/products/{product_id}/skus/{sku_id} - method: PATCH - auth: - - OAuth2: - - ecommerce:write - docs: > - Update a specified SKU. - - - Updating an existing SKU will set the Product type to `Advanced`, which - ensures all Product and SKU fields will be shown to users in the - Designer. - - - Required scope | `ecommerce:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - product_id: - type: string - docs: Unique identifier for a Product - sku_id: - type: string - docs: Unique identifier for a SKU - display-name: Update SKU - request: - name: ProductsUpdateSkuRequest - body: - properties: - publishStatus: optional - sku: root.Sku - content-type: application/json - response: - docs: Request was successful - type: root.Sku - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - product_id: 580e63fc8c9a982ac9b8b745 - sku_id: 5e8518516e147040726cc415 - request: - sku: - id: 66072fb71b89448912e2681c - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35Z' - lastUpdated: '2023-03-17T18:47:35Z' - createdOn: '2023-03-17T18:47:35Z' - fieldData: - name: Colorful T-shirt - Default - slug: colorful-t-shirt-default - price: - value: 2499 - unit: USD - currency: USD - response: - body: - id: 66072fb71b89448912e2681c - cmsLocaleId: 653ad57de882f528b32e810e - lastPublished: '2023-03-17T18:47:35Z' - lastUpdated: '2023-03-17T18:47:35Z' - createdOn: '2023-03-17T18:47:35Z' - fieldData: - sku-values: - color: blue - size: small - name: Colorful T-shirt - Default - slug: colorful-t-shirt-default - price: - value: 2499 - unit: USD - currency: USD - compare-at-price: - value: 100 - unit: USD - ec-sku-billing-method: one-time - ec-sku-subscription-plan: - interval: day - frequency: 1 - trial: 7 - plans: - - {} - main-image: https://www.example.com/image.jpg - sku: '1234567890' - sku-properties: - - id: Color - name: Color - enum: - - id: royal-blue - name: Royal Blue - slug: royal-blue - source: - openapi: ../../../openapi/referenced-specs/v2.yml -types: - ProductSkuCreateProduct: - properties: - fieldData: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - ProductSkuCreateSku: - properties: - fieldData: optional - source: - openapi: ../../../openapi/referenced-specs/v2.yml - inline: true - ProductsCreateSkuResponse: - properties: - skus: list - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/scripts.yml b/.mock/definition/scripts.yml deleted file mode 100644 index 089d5f8..0000000 --- a/.mock/definition/scripts.yml +++ /dev/null @@ -1,236 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/registered_scripts - method: GET - auth: - - OAuth2: - - custom_code:read - docs: > - Get a list of scripts that have been registered to a site. A site can - have a maximum of 800 registered scripts. - - - - To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. - - - - Required scope | `custom_code:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Get Registered Scripts - response: - docs: Request was successful - type: root.RegisteredScriptList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - registeredScripts: - - id: alert - canCopy: false - displayName: Alert - hostedLocation: https://cdn.webflow.io/.../alert-0.0.1.js - integrityHash: integrityHash - createdOn: '2022-10-26T00:28:54.191Z' - lastUpdated: lastUpdated - version: 0.0.1 - - id: alert - canCopy: false - displayName: Alert - hostedLocation: https://cdn.webflow.io/.../alert-0.0.2.js - integrityHash: integrityHash - createdOn: '2022-10-26T00:28:54.191Z' - lastUpdated: lastUpdated - version: 0.0.2 - - id: cms_slider - canCopy: true - displayName: CMS Slider - hostedLocation: https://cdn.jsdelivr.net/.../cms_slider.js - integrityHash: >- - sha384-J+YlJ8v0gpaRoKH7SbFbEmxOZlAxLiwNjfSsBhDooGa5roXlPPpXbEevck4J7YZ+ - createdOn: '2022-10-26T00:28:54.191Z' - lastUpdated: lastUpdated - version: 1.0.0 - pagination: - limit: 100 - offset: 0 - total: 3 - register-hosted: - path: /sites/{site_id}/registered_scripts/hosted - method: POST - auth: - - OAuth2: - - custom_code:write - docs: | - Register a hosted script to a site. - - - To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. - - - Required scope | `custom_code:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Register Script - Hosted - request: - name: CustomCodeHostedRequest - body: - properties: - hostedLocation: - type: string - docs: URI for an externally hosted script location - integrityHash: - type: string - docs: Sub-Resource Integrity Hash - canCopy: - type: optional - docs: >- - Define whether the script can be copied on site duplication and - transfer - default: false - version: - type: string - docs: >- - A Semantic Version (SemVer) string, denoting the version of the - script - displayName: - type: string - docs: >- - User-facing name for the script. Must be between 1 and 50 - alphanumeric characters - content-type: application/json - response: - docs: Request was successful - type: root.CustomCodeHostedResponse - status-code: 201 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - hostedLocation: hostedLocation - integrityHash: integrityHash - version: version - displayName: displayName - response: - body: - id: cms_slider - canCopy: true - displayName: CMS Slider - hostedLocation: https://cdn.jsdelivr.net/.../cmsslider.js - integrityHash: >- - sha384-J+YlJ8v0gpaRoKH7SbFbEmxOZlAxLiwNjfSsBhDooGa5roXlPPpXbEevck4J7YZ+ - createdOn: '2022-10-26T00:28:54.191Z' - lastUpdated: lastUpdated - version: 1.0.0 - register-inline: - path: /sites/{site_id}/registered_scripts/inline - method: POST - auth: - - OAuth2: - - custom_code:write - docs: > - Register an inline script to a site. Inline scripts are limited to 2000 - characters. - - - - To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. - - - - Required scope | `custom_code:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Register Script - Inline - request: - name: CustomCodeInlineRequest - body: - properties: - sourceCode: - type: string - docs: The code to be added to the site (to be hosted by Webflow). - integrityHash: - type: optional - docs: >- - Sub-Resource Integrity Hash. Only required for externally hosted - scripts (passed via hostedLocation) - canCopy: - type: optional - docs: >- - Define whether the script can be copied on site duplication and - transfer - default: false - version: - type: string - docs: >- - A Semantic Version (SemVer) string, denoting the version of the - script - displayName: - type: string - docs: >- - User-facing name for the script. Must be between 1 and 50 - alphanumeric characters - content-type: application/json - response: - docs: Created - type: root.CustomCodeInlineResponse - status-code: 201 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - name: CustomCodeInlineResponse - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - sourceCode: alert('hello world'); - version: 0.0.1 - displayName: Alert - response: - body: - id: alert - canCopy: false - displayName: Alert - hostedLocation: >- - https://uploads-ssl.webflow.com/6258612d1ee792848f805dcf%2F64b6c769ff52ba6c3d904a91%2F660d6e15b3d1696f2d2b1447%2Falert-0.0.1.js - integrityHash: integrityHash - createdOn: '2022-10-26T00:28:54.191Z' - lastUpdated: lastUpdated - version: 0.0.1 - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites.yml b/.mock/definition/sites.yml deleted file mode 100644 index ebc7cd0..0000000 --- a/.mock/definition/sites.yml +++ /dev/null @@ -1,558 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - create: - path: /workspaces/{workspace_id}/sites - method: POST - auth: - - OAuth2: - - sites:write - docs: > - Create a site. - - - This endpoint requires an Enterprise - workspace. - - - Required scope | `workspace:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - workspace_id: - type: string - docs: Unique identifier for a Workspace - display-name: Create Site - request: - name: SitesCreateRequest - body: - properties: - name: - type: string - docs: The name of the site - templateName: - type: optional - docs: The workspace or marketplace template to use - parentFolderId: - type: optional - docs: MegaDodo Publications - Potential Book Ideas - content-type: application/json - response: - docs: Request was successful - type: root.Site - status-code: 201 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - name: NewlyCreatedSite - path-parameters: - workspace_id: 580e63e98c9a982ac9b8b741 - request: - name: The Hitchhiker's Guide to the Galaxy - response: - body: - id: 670ecf86817e3cc7a510eb6a - workspaceId: 625860a7a6c16d624927122f - createdOn: '2024-10-15T20:24:38Z' - displayName: The Hitchiker's Guide - shortName: hitchikers-guide - lastPublished: '2016-10-24T19:43:17Z' - lastUpdated: '2024-10-15T20:24:38Z' - previewUrl: >- - https://dev-assets.website-files.com/580e63e98c9a982ac9b8b741/201610241243.png - timeZone: America/Los_Angeles - parentFolderId: 670ece123598db72d9648be1 - customDomains: - - id: 589a331aa51e760df7ccb89d - url: test-api-domain.com - lastPublished: '2022-12-07T16:51:37Z' - locales: - primary: - id: 653fd9af6a07fc9cfd7a5e57 - cmsLocaleId: 653ad57de882f528b32e810e - enabled: false - displayName: English (United States) - displayImageId: displayImageId - redirect: true - subdirectory: '' - tag: en-US - secondary: - - id: 653fd9af6a07fc9cfd7a5e57 - cmsLocaleId: 653ad57de882f528b32e810e - enabled: false - displayName: English (United States) - redirect: true - subdirectory: '' - tag: en-US - dataCollectionEnabled: true - dataCollectionType: always - list: - path: /sites - method: GET - auth: - - OAuth2: - - sites:read - docs: | - List of all sites the provided access token is able to access. - - Required scope | `sites:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - display-name: List Sites - response: - docs: Request was successful - type: root.Sites - status-code: 200 - errors: - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - examples: - - response: - body: - sites: - - id: 42e63e98c9a982ac9b8b741 - workspaceId: 42e63fc8c9a982ac9b8b744 - createdOn: '1979-10-12T12:00:00Z' - displayName: Heart of Gold Spaceship - shortName: heart-of-gold - lastPublished: '2023-04-02T12:42:00Z' - lastUpdated: '2016-10-24T19:43:17Z' - previewUrl: >- - https://dev-assets.website-files.com/42e63e98c9a982ac9b8b741/197910121200.png - timeZone: DeepSpace/InfiniteImprobability - parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 - customDomains: - - id: 589a331aa51e760df7ccb89e - url: heartofgold.galaxy - lastPublished: '2022-12-07T16:51:37Z' - locales: - primary: - id: 653fd9af6a07fc9cfd7a5e57 - cmsLocaleId: 653ad57de882f528b32e810e - enabled: true - displayName: English - Heart of Gold Standard - redirect: false - subdirectory: /en - tag: The Ultimate Answer - secondary: - - id: 653fd9af6a07fc9cfd7a5e58 - cmsLocaleId: 653ad57de882f528b32e810g - enabled: true - displayName: Betelgeusian - Vogon Liaison - redirect: true - subdirectory: /bet - tag: Vogon - - id: 653fd9af6a07fc9cfd7a5e59 - cmsLocaleId: 653ad57de882f528b32e810h - enabled: false - displayName: Magrathean - Custom Planet Designs - redirect: true - subdirectory: /mg - tag: Magrathean - dataCollectionEnabled: true - dataCollectionType: always - - id: 42e63e98c9a982ac9b8b742 - workspaceId: 42e63fc8c9a982ac9b8b745 - createdOn: '1981-10-12T12:00:00Z' - displayName: Marvin's Personal Blog - shortName: paranoid-android - lastPublished: '2023-04-02T12:45:00Z' - lastUpdated: '2016-10-24T19:43:17Z' - previewUrl: >- - https://dev-assets.website-files.com/42e63e98c9a982ac9b8b742/198110121200.png - timeZone: DeepSpace/Depression - parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 - customDomains: - - id: 589a331aa51e760df7ccb89f - url: marvin.blog - lastPublished: '2022-12-07T16:51:37Z' - locales: - primary: - id: 653fd9af6a07fc9cfd7a5e57 - cmsLocaleId: 653ad57de882f528b32e810e - enabled: true - displayName: English - Marvin's Musings - redirect: false - subdirectory: /en - tag: English - secondary: - - id: 653fd9af6a07fc9cfd7a5e56 - cmsLocaleId: 653ad57de882f528b32e810f - enabled: true - displayName: Squornshellous - Mattress Speak - redirect: true - subdirectory: /sr - tag: Squornshellous - dataCollectionEnabled: true - dataCollectionType: always - - id: 42e63e98c9a982ac9b8b743 - workspaceId: 42e63fc8c9a982ac9b8b746 - createdOn: '1982-10-12T12:00:00Z' - displayName: Vogon Poetry Archive - shortName: vogon-poetry - lastPublished: '2023-04-02T12:50:00Z' - lastUpdated: '2016-10-24T19:43:17Z' - previewUrl: >- - https://dev-assets.website-files.com/42e63e98c9a982ac9b8b743/198210121200.png - timeZone: Vogsphere/PoetryHall - parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 - customDomains: - - id: 589a331aa51e760df7ccb8a0 - url: vogonpoetry.galaxy - lastPublished: '2022-12-07T16:51:37Z' - locales: - primary: - id: 653fd9af6a07fc9cfd7a5e55 - cmsLocaleId: 653ad57de882f528b32e810d - enabled: true - displayName: English - Vogon Verse - redirect: false - subdirectory: /en - tag: Third Worst Poetry - secondary: - - id: 653fd9af6a07fc9cfd7a5e54 - cmsLocaleId: 653ad57de882f528b32e810c - enabled: true - displayName: Galactic - Universal Language - redirect: true - subdirectory: /gl - tag: Pan-Galactic Gargle Blaster - dataCollectionEnabled: true - dataCollectionType: always - get: - path: /sites/{site_id} - method: GET - auth: - - OAuth2: - - sites:read - docs: | - Get details of a site. - - Required scope | `sites:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Get Site - response: - docs: Request was successful - type: root.Site - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - name: SiteWithLocales - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - id: 42e98c9a982ac9b8b742 - workspaceId: 42e63e98c9a982ac9b8b742 - createdOn: '1979-10-12T12:00:00Z' - displayName: The Hitchhiker's Guide to the Galaxy - shortName: hitchhikers-guide - lastPublished: '2023-04-02T12:42:00Z' - lastUpdated: '2023-04-02T12:42:00Z' - previewUrl: >- - https://screenshots.webflow.com/sites/6258612d1ee792848f805dcf/20231219211811_d5990556c743f33b7071300a03bf67e6.png - timeZone: Magrathea/FactoryFloor - parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 - customDomains: - - id: 589a331aa51e760df7ccb89d - url: hitchhikersguide.galaxy - lastPublished: '2022-12-07T16:51:37Z' - - id: 589a331aa51e760df7ccb89e - url: heartofgold.spaceship - lastPublished: '2022-12-07T16:51:37Z' - locales: - primary: - id: 653fd9af6a07fc9cfd7a5e57 - cmsLocaleId: 653ad57de882f528b32e810e - enabled: false - displayName: English (United States) - displayImageId: displayImageId - redirect: true - subdirectory: '' - tag: en-US - secondary: - - id: 653fd9af6a07fc9cfd7a5e57 - cmsLocaleId: 653ad57de882f528b32e810e - enabled: false - displayName: English (United States) - redirect: true - subdirectory: '' - tag: en-US - dataCollectionEnabled: true - dataCollectionType: always - delete: - path: /sites/{site_id} - method: DELETE - auth: - - OAuth2: - - sites:write - docs: > - Delete a site. - - - This endpoint requires an Enterprise - workspace. - - - Required scope | `sites:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Delete Site - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - update: - path: /sites/{site_id} - method: PATCH - auth: - - OAuth2: - - sites:write - docs: > - Update a site. - - - This endpoint requires an Enterprise - workspace. - - - Required scope | `sites:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Update Site - request: - name: SitesUpdateRequest - body: - properties: - name: - type: optional - docs: The name of the site - parentFolderId: - type: optional - docs: The parent folder ID of the site - content-type: application/json - response: - docs: Request was successful - type: root.Site - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: {} - response: - body: - id: 42e98c9a982ac9b8b742 - workspaceId: 42e63e98c9a982ac9b8b742 - createdOn: '1979-10-12T12:00:00Z' - displayName: The Hitchhiker's Guide to the Galaxy - shortName: hitchhikers-guide - lastPublished: '2023-04-02T12:42:00Z' - lastUpdated: '2023-04-02T12:42:00Z' - previewUrl: >- - https://screenshots.webflow.com/sites/6258612d1ee792848f805dcf/20231219211811_d5990556c743f33b7071300a03bf67e6.png - timeZone: Magrathea/FactoryFloor - parentFolderId: 1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6 - customDomains: - - id: 589a331aa51e760df7ccb89d - url: hitchhikersguide.galaxy - lastPublished: '2022-12-07T16:51:37Z' - - id: 589a331aa51e760df7ccb89e - url: heartofgold.spaceship - lastPublished: '2022-12-07T16:51:37Z' - locales: - primary: - id: 653fd9af6a07fc9cfd7a5e57 - cmsLocaleId: 653ad57de882f528b32e810e - enabled: false - displayName: English (United States) - displayImageId: displayImageId - redirect: true - subdirectory: '' - tag: en-US - secondary: - - id: 653fd9af6a07fc9cfd7a5e57 - cmsLocaleId: 653ad57de882f528b32e810e - enabled: false - displayName: English (United States) - redirect: true - subdirectory: '' - tag: en-US - dataCollectionEnabled: true - dataCollectionType: always - get-custom-domain: - path: /sites/{site_id}/custom_domains - method: GET - auth: - - OAuth2: - - sites:read - docs: | - Get a list of all custom domains related to site. - - Required scope | `sites:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Get Custom Domains - response: - docs: Request was successful - type: root.Domains - status-code: 200 - errors: - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - customDomains: - - id: 589a331aa51e760df7ccb89d - url: hitchhikersguide.galaxy - lastPublished: '2022-12-07T16:51:37Z' - - id: 589a331aa51e760df7ccb89e - url: heartofgold.spaceship - lastPublished: '2022-12-07T16:51:37Z' - publish: - path: /sites/{site_id}/publish - method: POST - auth: - - OAuth2: - - sites:write - docs: > - Publishes a site to one or more more domains. - - - To publish to a specific custom domain, use the domain IDs from the [Get - Custom Domains](/data/reference/sites/get-custom-domain) endpoint. - - - This endpoint has a - specific rate limit of one successful publish queue per minute. - - - Required scope | `sites:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Publish Site - request: - name: SitesPublishRequest - body: - properties: - customDomains: - type: optional> - docs: Array of Custom Domain IDs to publish - publishToWebflowSubdomain: - type: optional - docs: Choice of whether to publish to the default Webflow Subdomain - default: false - content-type: application/json - response: - docs: Request accepted - type: SitesPublishResponse - status-code: 202 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - examples: - - name: DomainIDs - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - customDomains: - - 660c6449dd97ebc7346ac629 - - 660c6449dd97ebc7346ac62f - publishToWebflowSubdomain: false - response: - body: - customDomains: - - id: 589a331aa51e760df7ccb89d - url: test-api-domain.com - lastPublished: '2022-12-07T16:51:37Z' - publishToWebflowSubdomain: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml - display-name: Sites -docs: Sites are the sites in your Webflow workspace. -types: - SitesPublishResponse: - properties: - customDomains: - type: optional> - docs: Array of domains objects - publishToWebflowSubdomain: - type: optional - docs: Flag for publishing to webflow.io subdomain - default: false - source: - openapi: ../../../openapi/referenced-specs/v2.yml -webhooks: - site_publish: - audiences: [] - method: POST - display-name: Site Publish - headers: {} - payload: root.SitePublish - examples: - - payload: - triggerType: site_publish - payload: - siteId: 62749158efef318abc8d5a0f - publishedOn: '2024-07-26T16:43:20Z' - domains: - - heartofgold.webflow.io - publishedBy: - displayName: Zaphod BeebleBrox - docs: Information about a site that was published diff --git a/.mock/definition/sites/activityLogs.yml b/.mock/definition/sites/activityLogs.yml deleted file mode 100644 index 01f30f9..0000000 --- a/.mock/definition/sites/activityLogs.yml +++ /dev/null @@ -1,77 +0,0 @@ -imports: - root: ../__package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/activity_logs - method: GET - auth: - - OAuth2: - - site_activity:read - docs: > - Retrieve Activity Logs for a specific Site. - - - This endpoint requires an Enterprise - workspace. - - - Required scope: `site_activity:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Get Site Activity Logs - request: - name: ActivityLogsListRequest - query-parameters: - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - response: - docs: A list of site activity logs - type: root.SiteActivityLogResponse - status-code: 200 - errors: - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - query-parameters: - limit: 1 - offset: 1 - response: - body: - items: - - id: 654c16c7b229e56bcf26872d - createdOn: '2023-11-08T23:16:23Z' - lastUpdated: '2023-11-08T23:16:23Z' - event: cms_collection - resourceOperation: CREATED - user: - id: 6509cd56e90eec668b009712 - displayName: John Doe - resourceId: 654c16c7b229e56bcf26870c - resourceName: foo-bar - newValue: newValue - previousValue: previousValue - payload: - key: value - pagination: - limit: 25 - offset: 0 - total: 1 - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/comments.yml b/.mock/definition/sites/comments.yml deleted file mode 100644 index 3885152..0000000 --- a/.mock/definition/sites/comments.yml +++ /dev/null @@ -1,352 +0,0 @@ -types: - CommentsListCommentThreadsRequestSortBy: - enum: - - createdOn - - lastUpdated - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CommentsListCommentThreadsRequestSortOrder: - enum: - - asc - - desc - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CommentsGetCommentThreadRequestSortBy: - enum: - - createdOn - - lastUpdated - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CommentsGetCommentThreadRequestSortOrder: - enum: - - asc - - desc - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CommentsListCommentRepliesRequestSortBy: - enum: - - createdOn - - lastUpdated - source: - openapi: ../../../openapi/referenced-specs/v2.yml - CommentsListCommentRepliesRequestSortOrder: - enum: - - asc - - desc - source: - openapi: ../../../openapi/referenced-specs/v2.yml -imports: - root: ../__package__.yml -service: - auth: false - base-path: '' - endpoints: - list-comment-threads: - path: /sites/{site_id}/comments - method: GET - auth: - - OAuth2: - - comments:read - docs: | - List all comment threads for a site. - - - There may be a delay of up to 5 minutes before new comments appear in the system. - - - Required scope | `comments:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Comment Threads - request: - name: CommentsListCommentThreadsRequest - query-parameters: - localeId: - type: optional - docs: > - Unique identifier for a specific Locale. - - - [Lear more about - localization.](/data/v2.0.0/docs/working-with-localization) - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - sortBy: - type: optional - docs: >- - Sort results by the provided value. Only allowed when sortOrder is - provided. - sortOrder: - type: optional - docs: Sorts the results by asc or desc - response: - docs: Request was successful - type: root.CommentThreadList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - offset: 1 - limit: 1 - sortBy: createdOn - sortOrder: asc - response: - body: - comments: - - id: 679d2ddb5196117ad04d1ffa - siteId: 679826b3b20b045e176bc4b5 - pageId: 679826b3b20b045e176bc4bc - localeId: 67993753d910db250db64b3e - itemId: 580e64008c9a982ac9b8b754 - breakpoint: main - url: >- - https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc - content: 'Let''s go to the pub! [[6287ec36a841b25637c663df]] ' - isResolved: false - author: - userId: 6287ec36a841b25637c663df - email: ford.prefect@heartofgold.spaceship - name: Ford Prefect - mentionedUsers: - - userId: 6287ec36a841b25637c663df - email: arthur.dent@heartofgold.spaceship - name: Arthur Dent - createdOn: '2025-01-31T20:08:59.759Z' - lastUpdated: '2025-01-31T20:08:59.759Z' - - id: 679d2ddb5196117ad04d1ffc - siteId: 679826b3b20b045e176bc4b5 - pageId: 679826b3b20b045e176bc4bc - localeId: 67993753d910db250db64b3e - itemId: 580e64008c9a982ac9b8b754 - breakpoint: main - url: >- - https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc - content: >- - You have five minutes left to drink it - [[6287ec36a841b25637c663df]] - isResolved: false - author: - userId: 6287ec36a841b25637c663df - email: ford.prefect@heartofgold.spaceship - name: Ford Prefect - mentionedUsers: - - userId: 6287ec36a841b25637c663df - email: arthur.dent@heartofgold.spaceship - name: Arthur Dent - createdOn: '2025-01-31T20:08:59.759Z' - lastUpdated: '2025-01-31T20:08:59.759Z' - pagination: - limit: 2 - offset: 0 - total: 2 - get-comment-thread: - path: /sites/{site_id}/comments/{comment_thread_id} - method: GET - auth: - - OAuth2: - - comments:read - docs: | - Get details of a specific comment thread. - - - There may be a delay of up to 5 minutes before new comments appear in the system. - - - Required scope | `comments:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - comment_thread_id: - type: string - docs: Unique identifier for a Comment Thread - display-name: Get Comment Thread - request: - name: CommentsGetCommentThreadRequest - query-parameters: - localeId: - type: optional - docs: > - Unique identifier for a specific Locale. - - - [Lear more about - localization.](/data/v2.0.0/docs/working-with-localization) - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - sortBy: - type: optional - docs: >- - Sort results by the provided value. Only allowed when sortOrder is - provided. - sortOrder: - type: optional - docs: Sorts the results by asc or desc - response: - docs: Request was successful - type: root.CommentThread - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - comment_thread_id: 580e63e98c9a982ac9b8b741 - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - offset: 1 - limit: 1 - sortBy: createdOn - sortOrder: asc - response: - body: - id: 580e64008c9a982ac9b8b754 - siteId: 580e64008c9a982ac9b8b754 - pageId: 580e64008c9a982ac9b8b754 - localeId: 580e64008c9a982ac9b8b754 - itemId: 580e64008c9a982ac9b8b754 - breakpoint: main - url: >- - https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc - content: This is a comment reply - isResolved: true - author: - userId: userId - email: email - name: name - mentionedUsers: - - userId: 6287ec36a841b25637c663df - email: arthur.dent@heartofgold.spaceship - name: Arthur Dent - createdOn: '2023-03-17T18:47:35.560Z' - lastUpdated: '2023-03-17T18:47:35.560Z' - list-comment-replies: - path: /sites/{site_id}/comments/{comment_thread_id}/replies - method: GET - auth: - - OAuth2: - - comments:read - docs: | - List all replies to a specific comment thread. - - - There may be a delay of up to 5 minutes before new comments appear in the system. - - - Required scope | `comments:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - comment_thread_id: - type: string - docs: Unique identifier for a Comment Thread - display-name: List Comment Replies - request: - name: CommentsListCommentRepliesRequest - query-parameters: - localeId: - type: optional - docs: > - Unique identifier for a specific Locale. - - - [Lear more about - localization.](/data/v2.0.0/docs/working-with-localization) - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - sortBy: - type: optional - docs: >- - Sort results by the provided value. Only allowed when sortOrder is - provided. - sortOrder: - type: optional - docs: Sorts the results by asc or desc - response: - docs: Request was successful - type: root.CommentReplyList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - comment_thread_id: 580e63e98c9a982ac9b8b741 - query-parameters: - localeId: 65427cf400e02b306eaa04a0 - offset: 1 - limit: 1 - sortBy: createdOn - sortOrder: asc - response: - body: - comments: - - id: 679d2ddb5196117ad04d1ffa - commentId: 679d2ddb5196117ad04d1ff8 - siteId: 679826b3b20b045e176bc4b5 - pageId: 679826b3b20b045e176bc4bc - localeId: 67993753d910db250db64b3e - breakpoint: main - content: >- - This comment mentions another user - [[6287ec36a841b25637c663df]] - isResolved: false - author: - id: id - email: email - name: name - mentionedUsers: - - id: id - email: arthur.dent@example.com - name: Arthur Dent - lastUpdated: '2025-01-31T20:08:59.759Z' - createdOn: '2025-01-31T20:08:59.759Z' - pagination: - limit: 2 - offset: 0 - total: 1 - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/forms.yml b/.mock/definition/sites/forms.yml deleted file mode 100644 index 27e1e1d..0000000 --- a/.mock/definition/sites/forms.yml +++ /dev/null @@ -1,316 +0,0 @@ -imports: - root: ../__package__.yml -service: - auth: false - base-path: '' - endpoints: - list-submissions-by-site: - path: /sites/{site_id}/form_submissions - method: GET - auth: - - OAuth2: - - forms:read - docs: > - List all form submissions for a given site with the ability to filter - submissions by a centralized `elementId`. - - - Add `elementId` when you want to filter form submissions to a specific - form in a site. You can get the `elementId` from the [List forms - endpoint](/data/reference/forms/forms/list) (displayed as - `formElementId` in the response). - - - - - When a form is used in a Webflow component definition, each instance of - the component will yield a unique form. Adding the `elementId` in this - request ensures this API response includes all submissions from that - core form, wherever that form is used in instantiated components. - - - - - Use the [List Form Submissions - endpoint](/data/reference/forms/form-submissions/list-submissions) to - list form submissions for a given form ID. - - - Required scope | `forms:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Form Submissions by Site - request: - name: FormsListSubmissionsBySiteRequest - query-parameters: - elementId: - type: optional - docs: Identifier for an element - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - response: - docs: Request was successful - type: root.FormSubmissionList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - query-parameters: - elementId: 18259716-3e5a-646a-5f41-5dc4b9405aa0 - offset: 1 - limit: 1 - response: - body: - formSubmissions: - - id: 6321ca84df3949bfc6752327 - displayName: Sample Form - siteId: 62749158efef318abc8d5a0f - workspaceId: 62749158efef318abc8d5a0f - dateSubmitted: '2022-09-14T12:35:16Z' - formResponse: - First Name: Arthur - Last Name: Dent - - id: 660d64fabf6e0a0d4edab981 - displayName: Sample Form - siteId: 62749158efef318abc8d5a0f - workspaceId: 62749158efef318abc8d5a0f - dateSubmitted: '2022-09-14T12:35:16Z' - formResponse: - First Name: Ford - Last Name: Prefect - pagination: - limit: 25 - offset: 0 - total: 2 - list-submissions: - path: /sites/{site_id}/forms/{form_id}/submissions - method: GET - auth: - - OAuth2: - - forms:read - docs: > - List form submissions for a given form ID within a specific site. - - - Use the [List Form Submissions by Site - endpoint](/data/reference/forms/form-submissions/list-submissions-by-site) - to list form submissions for a given site with the ability to filter by - a `formElementId`. - - - Required scope | `forms:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - form_id: - type: string - docs: Unique identifier for a Form - display-name: List Form Submissions - request: - name: FormsListSubmissionsRequest - query-parameters: - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - response: - docs: Request was successful - type: root.FormSubmissionList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - form_id: 580e63e98c9a982ac9b8b741 - query-parameters: - offset: 1 - limit: 1 - response: - body: - formSubmissions: - - id: 6321ca84df3949bfc6752327 - displayName: Sample Form - siteId: 62749158efef318abc8d5a0f - workspaceId: 62749158efef318abc8d5a0f - dateSubmitted: '2022-09-14T12:35:16Z' - formResponse: - First Name: Arthur - Last Name: Dent - - id: 660d64fabf6e0a0d4edab981 - displayName: Sample Form - siteId: 62749158efef318abc8d5a0f - workspaceId: 62749158efef318abc8d5a0f - dateSubmitted: '2022-09-14T12:35:16Z' - formResponse: - First Name: Ford - Last Name: Prefect - pagination: - limit: 25 - offset: 0 - total: 2 - get-submission: - path: /sites/{site_id}/form_submissions/{form_submission_id} - method: GET - auth: - - OAuth2: - - forms:read - docs: | - Get information about a form submission within a specific site. - - Required scope | `forms:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - form_submission_id: - type: string - docs: Unique identifier for a Form Submission - display-name: Get Form Submission by Site - response: - docs: Request was successful - type: root.FormSubmission - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - form_submission_id: 580e63e98c9a982ac9b8b741 - response: - body: - id: 6321ca84df3949bfc6752327 - displayName: Sample Form - siteId: 62749158efef318abc8d5a0f - workspaceId: 62749158efef318abc8d5a0f - dateSubmitted: '2022-09-14T12:35:16Z' - formResponse: - First Name: Arthur - Last Name: Dent - delete-submission: - path: /sites/{site_id}/form_submissions/{form_submission_id} - method: DELETE - auth: - - OAuth2: - - forms:write - docs: | - Delete a form submission within a specific site. - - Required scope | `forms:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - form_submission_id: - type: string - docs: Unique identifier for a Form Submission - display-name: Delete Form Submission by Site - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - form_submission_id: 580e63e98c9a982ac9b8b741 - update-submission: - path: /sites/{site_id}/form_submissions/{form_submission_id} - method: PATCH - auth: - - OAuth2: - - forms:write - docs: | - Update hidden fields on a form submission within a specific site. - - Required scope | `forms:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - form_submission_id: - type: string - docs: Unique identifier for a Form Submission - display-name: Modify Form Submission by Site - request: - name: FormsUpdateSubmissionRequest - body: - properties: - formSubmissionData: - type: optional> - docs: >- - An existing **hidden field** defined on the form schema, and the - corresponding value to set - content-type: application/json - response: - docs: Request was successful - type: root.FormSubmission - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.ConflictError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - form_submission_id: 580e63e98c9a982ac9b8b741 - request: {} - response: - body: - id: 6321ca84df3949bfc6752327 - displayName: Sample Form - siteId: 62749158efef318abc8d5a0f - workspaceId: 62749158efef318abc8d5a0f - dateSubmitted: '2022-09-14T12:35:16Z' - formResponse: - First Name: Arthur - Last Name: Dent - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/plans.yml b/.mock/definition/sites/plans.yml deleted file mode 100644 index 4f662bc..0000000 --- a/.mock/definition/sites/plans.yml +++ /dev/null @@ -1,48 +0,0 @@ -imports: - root: ../__package__.yml -service: - auth: false - base-path: '' - endpoints: - get-site-plan: - path: /sites/{site_id}/plan - method: GET - auth: - - OAuth2: - - sites:read - docs: > - Get site plan details for the specified Site. - - - This endpoint requires an Enterprise - workspace. - - - Required scope | `sites:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Get Site Plan - response: - docs: Request was successful - type: root.SitePlan - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - id: hosting-business-v4 - name: Business Hosting - pricingInfo: https://webflow.com/pricing - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/redirects.yml b/.mock/definition/sites/redirects.yml deleted file mode 100644 index 806117c..0000000 --- a/.mock/definition/sites/redirects.yml +++ /dev/null @@ -1,221 +0,0 @@ -imports: - root: ../__package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/redirects - method: GET - auth: - - OAuth2: - - sites:read - docs: > - Fetch a list of all 301 redirect rules configured for a specific site. - - - Use this endpoint to review, audit, or manage the redirection rules that - control how traffic is rerouted on your site. - - - This endpoint requires an Enterprise - workspace. - - - Required scope: `sites:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Get 301 redirects - response: - docs: Request was successful - type: root.Redirects - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - redirects: - - id: 42e1a2b7aa1a13f768a0042a - fromUrl: /mostly-harmless - toUrl: /earth - - id: 6x9e7f8d9a4b1c2d3e4f5678 - fromUrl: /babel-fish - toUrl: /translate - pagination: - limit: 100 - offset: 0 - total: 2 - create: - path: /sites/{site_id}/redirects - method: POST - auth: - - OAuth2: - - sites:write - docs: > - Add a new 301 redirection rule to a site. - - - This endpoint allows you to define a source path (`fromUrl`) and its - corresponding destination path (`toUrl`), which will dictate how traffic - is rerouted on your site. This is useful for managing site changes, - restructuring URLs, or handling outdated links. - - - This endpoint requires an Enterprise - workspace. - - - Required scope: `sites:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Create a 301 redirect - request: - body: root.Redirect - content-type: application/json - response: - docs: Request was successful - type: root.Redirect - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - id: 42e1a2b7aa1a13f768a0042a - fromUrl: /mostly-harmless - toUrl: /earth - response: - body: - id: 42e1a2b7aa1a13f768a0042a - fromUrl: /mostly-harmless - toUrl: /earth - delete: - path: /sites/{site_id}/redirects/{redirect_id} - method: DELETE - auth: - - OAuth2: - - sites:write - docs: > - Remove a 301 redirection rule from a site. - - - This is useful for cleaning up outdated or unnecessary redirects, - ensuring that your site's routing behavior remains efficient and - up-to-date. - - - This endpoint requires an Enterprise - workspace. - - - Required scope: `sites:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - redirect_id: - type: string - docs: Unique identifier site rediect - display-name: Delete 301 redirects - response: - docs: Request was successful - type: root.Redirects - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - redirect_id: 66c4cb9a20cac35ed19500e6 - response: - body: - redirects: - - id: 42e1a2b7aa1a13f768a0042a - fromUrl: /mostly-harmless - toUrl: /earth - - id: 6x9e7f8d9a4b1c2d3e4f5678 - fromUrl: /babel-fish - toUrl: /translate - pagination: - limit: 100 - offset: 0 - total: 2 - update: - path: /sites/{site_id}/redirects/{redirect_id} - method: PATCH - auth: - - OAuth2: - - sites:write - docs: > - Update a 301 redirection rule from a site. - - - This endpoint requires an Enterprise - workspace. - - - Required scope: `sites:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - redirect_id: - type: string - docs: Unique identifier site rediect - display-name: Update 301 redirect - request: - body: root.Redirect - content-type: application/json - response: - docs: Request was successful - type: root.Redirect - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - redirect_id: 66c4cb9a20cac35ed19500e6 - request: - id: 42e1a2b7aa1a13f768a0042a - fromUrl: /mostly-harmless - toUrl: /earth - response: - body: - id: 42e1a2b7aa1a13f768a0042a - fromUrl: /mostly-harmless - toUrl: /earth - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/robotsTxt.yml b/.mock/definition/sites/robotsTxt.yml deleted file mode 100644 index 1aaf6cf..0000000 --- a/.mock/definition/sites/robotsTxt.yml +++ /dev/null @@ -1,229 +0,0 @@ -imports: - root: ../__package__.yml -service: - auth: false - base-path: '' - endpoints: - get: - path: /sites/{site_id}/robots_txt - method: GET - auth: - - OAuth2: - - site_config:read - docs: > - Retrieve the robots.txt configuration for various user agents. - - - This endpoint requires an Enterprise - workspace. - - - Required scope: `site_config:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Get robots.txt - response: - docs: Request was successful - type: root.Robots - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - rules: - - userAgent: googlebot - allows: - - /public - disallows: - - /vogon-poetry - - /total-perspective-vortex - sitemap: https://heartofgold.ship/sitemap.xml - put: - path: /sites/{site_id}/robots_txt - method: PUT - auth: - - OAuth2: - - site_config:write - docs: > - Replace the `robots.txt` configuration for various user agents. - - - This endpoint requires an Enterprise - workspace. - - - Required scope | `site_config:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Replace robots.txt - request: - body: root.Robots - content-type: application/json - response: - docs: Request was successful - type: root.Robots - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - rules: - - userAgent: googlebot - allows: - - /public - disallows: - - /vogon-poetry - - /total-perspective-vortex - sitemap: https://heartofgold.ship/sitemap.xml - response: - body: - rules: - - userAgent: googlebot - allows: - - /public - disallows: - - /vogon-poetry - - /total-perspective-vortex - sitemap: https://heartofgold.ship/sitemap.xml - delete: - path: /sites/{site_id}/robots_txt - method: DELETE - auth: - - OAuth2: - - site_config:write - docs: > - Remove specific rules for a user-agent in your `robots.txt` file. To - delete all rules for a user-agent, provide an empty rule set. This will - remove the user-agent's entry entirely, leaving it subject to your - site's default crawling behavior. - - - **Note:** Deleting a user-agent with no rules will make the user-agent's - access unrestricted unless other directives apply. - - - This endpoint requires an Enterprise - workspace. - - - Required scope: `site_config:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Delete robots.txt - request: - body: root.Robots - content-type: application/json - response: - docs: Request was successful - type: root.Robots - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - rules: - - userAgent: '*' - allows: - - /public - disallows: - - /bubbles - response: - body: - rules: - - userAgent: googlebot - allows: - - /public - disallows: - - /vogon-poetry - - /total-perspective-vortex - sitemap: https://heartofgold.ship/sitemap.xml - patch: - path: /sites/{site_id}/robots_txt - method: PATCH - auth: - - OAuth2: - - site_config:write - docs: > - Update the `robots.txt` configuration for various user agents. - - - This endpoint requires an Enterprise - workspace. - - - Required scope | `site_config:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Update robots.txt - request: - body: root.Robots - content-type: application/json - response: - docs: Request was successful - type: root.Robots - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - rules: - - userAgent: googlebot - allows: - - /public - disallows: - - /vogon-poetry - - /total-perspective-vortex - sitemap: https://heartofgold.ship/sitemap.xml - response: - body: - rules: - - userAgent: googlebot - allows: - - /public - disallows: - - /vogon-poetry - - /total-perspective-vortex - sitemap: https://heartofgold.ship/sitemap.xml - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/scripts.yml b/.mock/definition/sites/scripts.yml deleted file mode 100644 index 6762c85..0000000 --- a/.mock/definition/sites/scripts.yml +++ /dev/null @@ -1,243 +0,0 @@ -imports: - root: ../__package__.yml -service: - auth: false - base-path: '' - endpoints: - get-custom-code: - path: /sites/{site_id}/custom_code - method: GET - auth: - - OAuth2: - - custom_code:read - docs: | - Get all scripts applied to a site by the App. - - - To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. - - - Required scope | `custom_code:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Get Custom Code - response: - docs: Request was successful - type: root.ScriptApplyList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - scripts: - - id: cms_slider - location: header - version: 1.0.0 - attributes: - my-attribute: some-value - - id: alert - location: header - version: 0.0.1 - attributes: - key: value - lastUpdated: '2022-10-26T00:28:54.191Z' - createdOn: '2022-10-26T00:28:54.191Z' - upsert-custom-code: - path: /sites/{site_id}/custom_code - method: PUT - auth: - - OAuth2: - - custom_code:write - docs: > - Apply registered scripts to a site. If you have multiple scripts your - App needs to apply or maintain on a site, ensure they are always - included in the request body for this endpoint. To remove individual - scripts, simply call this endpoint without the script in the request - body. - - - - To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. - - - - Required scope | `custom_code:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Add/Update Custom Code - request: - body: root.ScriptApplyList - content-type: application/json - response: - docs: Request was successful - type: root.ScriptApplyList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - scripts: - - id: cms_slider - location: header - version: 1.0.0 - attributes: - my-attribute: some-value - - id: alert - location: header - version: 0.0.1 - response: - body: - scripts: - - id: cms_slider - location: header - version: 1.0.0 - attributes: - my-attribute: some-value - - id: alert - location: header - version: 0.0.1 - attributes: - key: value - lastUpdated: lastUpdated - createdOn: createdOn - delete-custom-code: - path: /sites/{site_id}/custom_code - method: DELETE - auth: - - OAuth2: - - custom_code:write - docs: > - Remove all scripts from a site applied by the App. This endpoint will - not remove scripts from the site's registered scripts. - - - To remove individual scripts applied by the App, use the [Add/Update - Custom - Code](/data/reference/custom-code/custom-code-sites/upsert-custom-code) - endpoint. - - - Access to this endpoint requires a bearer token obtained from an - [OAuth Code Grant Flow](/data/reference/oauth-app). - - - Required scope | `custom_code:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Delete Custom Code - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - list-custom-code-blocks: - path: /sites/{site_id}/custom_code/blocks - method: GET - auth: - - OAuth2: - - custom_code:read - docs: > - Get a list of scripts that have been applied to a site and/or individual - pages. - - - - To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. - - See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. - - - - Required scope | `custom_code:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Custom Code Blocks - request: - name: ScriptsListCustomCodeBlocksRequest - query-parameters: - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - response: - docs: Request was successful - type: root.ListCustomCodeBlocks - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - query-parameters: - offset: 1 - limit: 1 - response: - body: - blocks: - - siteId: 6258612d1ee792848f805dcf - pageId: pageId - type: site - scripts: - - id: chartjs - location: header - version: 4.4.2 - attributes: - key: value - createdOn: '2024-04-03T16:49:15Z' - lastUpdated: '2024-04-03T16:49:15Z' - - siteId: 6390c49674a71f84b51a08d8 - pageId: 6419db964a9c43f6a3af6348 - type: page - scripts: - - id: id - location: header - version: version - createdOn: '2022-10-26T00:28:54Z' - lastUpdated: '2022-10-26T00:28:54Z' - pagination: - limit: 10 - offset: 0 - total: 1 - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/sites/wellKnown.yml b/.mock/definition/sites/wellKnown.yml deleted file mode 100644 index 10ef3e0..0000000 --- a/.mock/definition/sites/wellKnown.yml +++ /dev/null @@ -1,130 +0,0 @@ -types: - WellKnownFileContentType: - enum: - - value: application/json - name: ApplicationJson - - value: text/plain - name: TextPlain - docs: The content type of the file. Defaults to application/json - default: application/json - inline: true - source: - openapi: ../../../openapi/referenced-specs/v2.yml -imports: - root: ../__package__.yml -service: - auth: false - base-path: '' - endpoints: - put: - path: /sites/{site_id}/well_known - method: PUT - auth: - - OAuth2: - - site_config:write - docs: > - Upload a supported well-known file to a site. - - - The current restrictions on well-known files are as follows: - - Each file must be smaller than 100kb - - Less than 30 total files - - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` - - - `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. - - - This endpoint requires an Enterprise - workspace. - - - Required scope: `site_config:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Set a well-known file - request: - name: WellKnownFile - body: - properties: - fileName: - type: string - docs: The name of the file - fileData: - type: string - docs: The contents of the file - contentType: - type: optional - docs: The content type of the file. Defaults to application/json - default: application/json - content-type: application/json - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - fileName: apple-app-site-association.txt - fileData: | - { - "applinks": { - "apps": [], - "details": [ - { - "appID": "ABCDE12345.com.example.app", - "paths": [ "/*", "/some/path/*" ] - } - ] - } - } - contentType: application/json - delete: - path: /sites/{site_id}/well_known - method: DELETE - auth: - - OAuth2: - - site_config:write - docs: > - Delete existing well-known files from a site. - - - This endpoint requires an Enterprise - workspace. - - - Required scope: `site_config:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Delete a well-known file - request: - name: WellKnownDeleteRequest - body: - properties: - fileNames: - type: optional> - docs: A list of file names to delete - content-type: application/json - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: {} - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/token.yml b/.mock/definition/token.yml deleted file mode 100644 index 4b0e365..0000000 --- a/.mock/definition/token.yml +++ /dev/null @@ -1,75 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - authorized-by: - path: /token/authorized_by - method: GET - auth: - - OAuth2: - - authorized_user:read - docs: | - Information about the Authorized User - - Required Scope | `authorized_user:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - display-name: Get Authorization User Info - response: - docs: Request was successful - type: root.AuthorizedUser - status-code: 200 - errors: - - root.UnauthorizedError - - root.ForbiddenError - examples: - - response: - body: - id: 545bbecb7bdd6769632504a7 - email: some@email.com - firstName: Some - lastName: One - introspect: - path: /token/introspect - method: GET - docs: > - Information about the authorization token - - - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). - source: - openapi: ../../../openapi/referenced-specs/v2.yml - display-name: Get Authorization Info - response: - docs: Request was successful - type: root.Authorization - status-code: 200 - errors: - - root.UnauthorizedError - examples: - - response: - body: - authorization: - id: 55818d58616600637b9a5786 - createdOn: '2016-10-03T23:12:00Z' - lastUsed: '2016-10-10T21:41:12Z' - grantType: authorization_code - rateLimit: 60 - scope: assets:read,assets:write - authorizedTo: - siteIds: - - 62f3b1f7eafac55d0c64ef91 - workspaceIds: - - 52f3b1f7eafac55d0c64ef91 - userIds: - - 545bbecb7bdd6769632504a7 - application: - id: 55131cd036c09f7d07883dfc - description: My Amazing App - homepage: https://webflow.com - displayName: My Amazing App - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/definition/webhooks.yml b/.mock/definition/webhooks.yml deleted file mode 100644 index 46bbb02..0000000 --- a/.mock/definition/webhooks.yml +++ /dev/null @@ -1,188 +0,0 @@ -imports: - root: __package__.yml -service: - auth: false - base-path: '' - endpoints: - list: - path: /sites/{site_id}/webhooks - method: GET - docs: | - List all App-created Webhooks registered for a given site - - Required scope | `sites:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: List Webhooks - response: - docs: Request was successful - type: root.WebhookList - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - response: - body: - webhooks: - - id: 57ca0a9e418c504a6e1acbb6 - triggerType: form_submission - url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f - workspaceId: 4f4e46fd476ea8c507000001 - siteId: 562ac0395358780a1f5e6fbd - filter: - name: Email Form - lastTriggered: '2023-02-08T23:59:28Z' - createdOn: '2016-09-02T23:26:22Z' - - id: 578d85cce0c47cd2865f4cf2 - triggerType: form_submission - url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f - workspaceId: 4f4e46fd476ea8c507000001 - siteId: 562ac0395358780a1f5e6fbd - filter: - name: Email Form - lastTriggered: '2023-02-08T23:59:28Z' - createdOn: '2016-07-19T01:43:40Z' - - id: 578d85cce0c47cd2865f4cf3 - triggerType: form_submission - url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f - workspaceId: 4f4e46fd476ea8c507000001 - siteId: 562ac0395358780a1f5e6fbd - filter: - name: Email Form - lastTriggered: '2023-02-08T23:59:28Z' - createdOn: '2016-07-19T01:43:40Z' - pagination: - limit: 100 - offset: 0 - total: 100 - create: - path: /sites/{site_id}/webhooks - method: POST - docs: > - Create a new Webhook. - - - Limit of 75 registrations per `triggerType`, per site. - - - Access to this endpoint requires a bearer token from a [Data - Client App](/data/docs/getting-started-data-clients). - - Required scope | `sites:write` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - site_id: - type: string - docs: Unique identifier for a Site - display-name: Create Webhook - request: - body: root.Webhook - content-type: application/json - response: - docs: Request was successful - type: root.Webhook - status-code: 201 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - site_id: 580e63e98c9a982ac9b8b741 - request: - id: 582266e0cd48de0f0e3c6d8b - triggerType: form_submission - url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f - workspaceId: 4f4e46fd476ea8c507000001 - siteId: 562ac0395358780a1f5e6fbd - lastTriggered: '2023-02-08T23:59:28Z' - createdOn: '2022-11-08T23:59:28Z' - response: - body: - id: 582266e0cd48de0f0e3c6d8b - triggerType: form_submission - url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f - workspaceId: 4f4e46fd476ea8c507000001 - siteId: 562ac0395358780a1f5e6fbd - filter: - name: My Form - lastTriggered: '2023-02-08T23:59:28Z' - createdOn: '2022-11-08T23:59:28Z' - get: - path: /webhooks/{webhook_id} - method: GET - docs: | - Get a specific Webhook instance - - Required scope: `sites:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - webhook_id: - type: string - docs: Unique identifier for a Webhook - display-name: Get Webhook - response: - docs: Request was successful - type: root.Webhook - status-code: 200 - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - webhook_id: 580e64008c9a982ac9b8b754 - response: - body: - id: 582266e0cd48de0f0e3c6d8b - triggerType: form_submission - url: https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f - workspaceId: 4f4e46fd476ea8c507000001 - siteId: 562ac0395358780a1f5e6fbd - filter: - name: My Form - lastTriggered: '2023-02-08T23:59:28Z' - createdOn: '2022-11-08T23:59:28Z' - delete: - path: /webhooks/{webhook_id} - method: DELETE - docs: | - Remove a Webhook - - Required scope: `sites:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - webhook_id: - type: string - docs: Unique identifier for a Webhook - display-name: Remove Webhook - errors: - - root.BadRequestError - - root.UnauthorizedError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - webhook_id: 580e64008c9a982ac9b8b754 - source: - openapi: ../../../openapi/referenced-specs/v2.yml - display-name: Webhooks -docs: Webhooks are the webhooks in your Webflow site. diff --git a/.mock/definition/workspaces/auditLogs.yml b/.mock/definition/workspaces/auditLogs.yml deleted file mode 100644 index 57b604a..0000000 --- a/.mock/definition/workspaces/auditLogs.yml +++ /dev/null @@ -1,126 +0,0 @@ -types: - AuditLogsGetWorkspaceAuditLogsRequestSortOrder: - enum: - - asc - - desc - source: - openapi: ../../../openapi/referenced-specs/v2.yml - AuditLogsGetWorkspaceAuditLogsRequestEventType: - enum: - - user_access - - custom_role - - workspace_membership - - site_membership - - workspace_invitation - - workspace_setting - source: - openapi: ../../../openapi/referenced-specs/v2.yml -imports: - root: ../__package__.yml -service: - auth: false - base-path: '' - endpoints: - get-workspace-audit_logs: - path: /workspaces/{workspace_id_or_slug}/audit_logs - method: GET - auth: - - OAuth2: - - workspace_activity:read - docs: > - Get audit logs for a workspace. - - - This endpoint - requires an Enterprise workspace and a workspace token with the - `workspace_activity:read` scope. Create a workspace token from your - workspace dashboard integrations page to use this endpoint. - - - Required scope | `workspace_activity:read` - source: - openapi: ../../../openapi/referenced-specs/v2.yml - path-parameters: - workspace_id_or_slug: - type: string - docs: Unique identifier or slug for a Workspace - display-name: Get Workspace Audit Logs - request: - name: AuditLogsGetWorkspaceAuditLogsRequest - query-parameters: - limit: - type: optional - docs: 'Maximum number of records to be returned (max limit: 100)' - offset: - type: optional - docs: >- - Offset used for pagination if the results have more than limit - records - sortOrder: - type: optional - docs: Sorts the results by asc or desc - eventType: - type: optional - docs: The event type to filter by - from: - type: optional - docs: The start date to filter by - to: - type: optional - docs: The end date to filter by - response: - docs: A list of workspace audit logs - type: root.WorkspaceAuditLogResponse - status-code: 200 - errors: - - root.UnauthorizedError - - root.ForbiddenError - - root.NotFoundError - - root.TooManyRequestsError - - root.InternalServerError - examples: - - path-parameters: - workspace_id_or_slug: hitchhikers-workspace - query-parameters: - limit: 1 - offset: 1 - sortOrder: asc - eventType: user_access - from: '2025-06-22T16:00:31Z' - to: '2025-07-22T16:00:31Z' - response: - body: - items: - - eventSubType: login - eventType: user_access - timestamp: '2025-04-29T20:30:06Z' - actor: - id: 6661ccb359b561c69f29d554 - email: someone@email.com - workspace: - id: 6621ccb459b561c69f29d57c - slug: hitchhikers-workspace - - eventSubType: user_added - eventType: workspace_membership - timestamp: '2025-04-30T20:30:06Z' - actor: - id: 60492e55bbddce079561cd7a - email: someone@webflow.com - workspace: - id: 6621ccb459b561c69f29d57c - slug: hitchhikers-workspace - - eventSubType: user_added - eventType: site_membership - timestamp: '2025-04-30T00:33:31Z' - actor: - id: 671fe00d185fc8c1ad409d37 - email: someone@webflow.com - workspace: - id: 6621ccb459b561c69f29d57c - slug: hitchhikers-workspace - pagination: - limit: 10 - offset: 0 - total: 3 - source: - openapi: ../../../openapi/referenced-specs/v2.yml diff --git a/.mock/fern.config.json b/.mock/fern.config.json deleted file mode 100644 index 9c2f634..0000000 --- a/.mock/fern.config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "organization" : "webflow", - "version" : "0.110.1" -} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..eb82e56 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Webflow. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index ea2269c..83fdc8b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -75,6 +75,20 @@ typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "execnet" +version = "2.1.2" +description = "execnet: rapid multi-Python deployment" +optional = false +python-versions = ">=3.8" +files = [ + {file = "execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec"}, + {file = "execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd"}, +] + +[package.extras] +testing = ["hatch", "pre-commit", "pytest", "tox"] + [[package]] name = "h11" version = "0.16.0" @@ -158,48 +172,55 @@ files = [ [[package]] name = "mypy" -version = "1.0.1" +version = "1.13.0" description = "Optional static typing for Python" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "mypy-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:71a808334d3f41ef011faa5a5cd8153606df5fc0b56de5b2e89566c8093a0c9a"}, - {file = "mypy-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:920169f0184215eef19294fa86ea49ffd4635dedfdea2b57e45cb4ee85d5ccaf"}, - {file = "mypy-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27a0f74a298769d9fdc8498fcb4f2beb86f0564bcdb1a37b58cbbe78e55cf8c0"}, - {file = "mypy-1.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:65b122a993d9c81ea0bfde7689b3365318a88bde952e4dfa1b3a8b4ac05d168b"}, - {file = "mypy-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:5deb252fd42a77add936b463033a59b8e48eb2eaec2976d76b6878d031933fe4"}, - {file = "mypy-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2013226d17f20468f34feddd6aae4635a55f79626549099354ce641bc7d40262"}, - {file = "mypy-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:48525aec92b47baed9b3380371ab8ab6e63a5aab317347dfe9e55e02aaad22e8"}, - {file = "mypy-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c96b8a0c019fe29040d520d9257d8c8f122a7343a8307bf8d6d4a43f5c5bfcc8"}, - {file = "mypy-1.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:448de661536d270ce04f2d7dddaa49b2fdba6e3bd8a83212164d4174ff43aa65"}, - {file = "mypy-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:d42a98e76070a365a1d1c220fcac8aa4ada12ae0db679cb4d910fabefc88b994"}, - {file = "mypy-1.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e64f48c6176e243ad015e995de05af7f22bbe370dbb5b32bd6988438ec873919"}, - {file = "mypy-1.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fdd63e4f50e3538617887e9aee91855368d9fc1dea30da743837b0df7373bc4"}, - {file = "mypy-1.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dbeb24514c4acbc78d205f85dd0e800f34062efcc1f4a4857c57e4b4b8712bff"}, - {file = "mypy-1.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a2948c40a7dd46c1c33765718936669dc1f628f134013b02ff5ac6c7ef6942bf"}, - {file = "mypy-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5bc8d6bd3b274dd3846597855d96d38d947aedba18776aa998a8d46fabdaed76"}, - {file = "mypy-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:17455cda53eeee0a4adb6371a21dd3dbf465897de82843751cf822605d152c8c"}, - {file = "mypy-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e831662208055b006eef68392a768ff83596035ffd6d846786578ba1714ba8f6"}, - {file = "mypy-1.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e60d0b09f62ae97a94605c3f73fd952395286cf3e3b9e7b97f60b01ddfbbda88"}, - {file = "mypy-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:0af4f0e20706aadf4e6f8f8dc5ab739089146b83fd53cb4a7e0e850ef3de0bb6"}, - {file = "mypy-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:24189f23dc66f83b839bd1cce2dfc356020dfc9a8bae03978477b15be61b062e"}, - {file = "mypy-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93a85495fb13dc484251b4c1fd7a5ac370cd0d812bbfc3b39c1bafefe95275d5"}, - {file = "mypy-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f546ac34093c6ce33f6278f7c88f0f147a4849386d3bf3ae193702f4fe31407"}, - {file = "mypy-1.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c6c2ccb7af7154673c591189c3687b013122c5a891bb5651eca3db8e6c6c55bd"}, - {file = "mypy-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:15b5a824b58c7c822c51bc66308e759243c32631896743f030daf449fe3677f3"}, - {file = "mypy-1.0.1-py3-none-any.whl", hash = "sha256:eda5c8b9949ed411ff752b9a01adda31afe7eae1e53e946dbdf9db23865e66c4"}, - {file = "mypy-1.0.1.tar.gz", hash = "sha256:28cea5a6392bb43d266782983b5a4216c25544cd7d80be681a155ddcdafd152d"}, + {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"}, + {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"}, + {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"}, + {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"}, + {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"}, + {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"}, + {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"}, + {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"}, + {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"}, + {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"}, + {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"}, + {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"}, + {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"}, + {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"}, + {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"}, + {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"}, + {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"}, + {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"}, + {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"}, + {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"}, + {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"}, + {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"}, ] [package.dependencies] -mypy-extensions = ">=0.4.3" +mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=3.10" +typing-extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] +faster-cache = ["orjson"] install-types = ["pip"] -python2 = ["typed-ast (>=1.4.0,<2)"] +mypyc = ["setuptools (>=50)"] reports = ["lxml"] [[package]] @@ -411,6 +432,26 @@ pytest = ">=7.0.0,<9" docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] +[[package]] +name = "pytest-xdist" +version = "3.6.1" +description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7"}, + {file = "pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d"}, +] + +[package.dependencies] +execnet = ">=2.1" +pytest = ">=7.0.0" + +[package.extras] +psutil = ["psutil (>=3.0)"] +setproctitle = ["setproctitle"] +testing = ["filelock"] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -427,29 +468,29 @@ six = ">=1.5" [[package]] name = "ruff" -version = "0.5.7" +version = "0.11.5" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.5.7-py3-none-linux_armv6l.whl", hash = "sha256:548992d342fc404ee2e15a242cdbea4f8e39a52f2e7752d0e4cbe88d2d2f416a"}, - {file = "ruff-0.5.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:00cc8872331055ee017c4f1071a8a31ca0809ccc0657da1d154a1d2abac5c0be"}, - {file = "ruff-0.5.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eaf3d86a1fdac1aec8a3417a63587d93f906c678bb9ed0b796da7b59c1114a1e"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a01c34400097b06cf8a6e61b35d6d456d5bd1ae6961542de18ec81eaf33b4cb8"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcc8054f1a717e2213500edaddcf1dbb0abad40d98e1bd9d0ad364f75c763eea"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f70284e73f36558ef51602254451e50dd6cc479f8b6f8413a95fcb5db4a55fc"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a78ad870ae3c460394fc95437d43deb5c04b5c29297815a2a1de028903f19692"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ccd078c66a8e419475174bfe60a69adb36ce04f8d4e91b006f1329d5cd44bcf"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e31c9bad4ebf8fdb77b59cae75814440731060a09a0e0077d559a556453acbb"}, - {file = "ruff-0.5.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d796327eed8e168164346b769dd9a27a70e0298d667b4ecee6877ce8095ec8e"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a09ea2c3f7778cc635e7f6edf57d566a8ee8f485f3c4454db7771efb692c499"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a36d8dcf55b3a3bc353270d544fb170d75d2dff41eba5df57b4e0b67a95bb64e"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9369c218f789eefbd1b8d82a8cf25017b523ac47d96b2f531eba73770971c9e5"}, - {file = "ruff-0.5.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b88ca3db7eb377eb24fb7c82840546fb7acef75af4a74bd36e9ceb37a890257e"}, - {file = "ruff-0.5.7-py3-none-win32.whl", hash = "sha256:33d61fc0e902198a3e55719f4be6b375b28f860b09c281e4bdbf783c0566576a"}, - {file = "ruff-0.5.7-py3-none-win_amd64.whl", hash = "sha256:083bbcbe6fadb93cd86709037acc510f86eed5a314203079df174c40bbbca6b3"}, - {file = "ruff-0.5.7-py3-none-win_arm64.whl", hash = "sha256:2dca26154ff9571995107221d0aeaad0e75a77b5a682d6236cf89a58c70b76f4"}, - {file = "ruff-0.5.7.tar.gz", hash = "sha256:8dfc0a458797f5d9fb622dd0efc52d796f23f0a1493a9527f4e49a550ae9a7e5"}, + {file = "ruff-0.11.5-py3-none-linux_armv6l.whl", hash = "sha256:2561294e108eb648e50f210671cc56aee590fb6167b594144401532138c66c7b"}, + {file = "ruff-0.11.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ac12884b9e005c12d0bd121f56ccf8033e1614f736f766c118ad60780882a077"}, + {file = "ruff-0.11.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4bfd80a6ec559a5eeb96c33f832418bf0fb96752de0539905cf7b0cc1d31d779"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0947c0a1afa75dcb5db4b34b070ec2bccee869d40e6cc8ab25aca11a7d527794"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad871ff74b5ec9caa66cb725b85d4ef89b53f8170f47c3406e32ef040400b038"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6cf918390cfe46d240732d4d72fa6e18e528ca1f60e318a10835cf2fa3dc19f"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56145ee1478582f61c08f21076dc59153310d606ad663acc00ea3ab5b2125f82"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e5f66f8f1e8c9fc594cbd66fbc5f246a8d91f916cb9667e80208663ec3728304"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80b4df4d335a80315ab9afc81ed1cff62be112bd165e162b5eed8ac55bfc8470"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3068befab73620b8a0cc2431bd46b3cd619bc17d6f7695a3e1bb166b652c382a"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f5da2e710a9641828e09aa98b92c9ebbc60518fdf3921241326ca3e8f8e55b8b"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ef39f19cb8ec98cbc762344921e216f3857a06c47412030374fffd413fb8fd3a"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b2a7cedf47244f431fd11aa5a7e2806dda2e0c365873bda7834e8f7d785ae159"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:81be52e7519f3d1a0beadcf8e974715b2dfc808ae8ec729ecfc79bddf8dbb783"}, + {file = "ruff-0.11.5-py3-none-win32.whl", hash = "sha256:e268da7b40f56e3eca571508a7e567e794f9bfcc0f412c4b607931d3af9c4afe"}, + {file = "ruff-0.11.5-py3-none-win_amd64.whl", hash = "sha256:6c6dc38af3cfe2863213ea25b6dc616d679205732dc0fb673356c2d69608f800"}, + {file = "ruff-0.11.5-py3-none-win_arm64.whl", hash = "sha256:67e241b4314f4eacf14a601d586026a962f4002a475aa702c69980a38087aa4e"}, + {file = "ruff-0.11.5.tar.gz", hash = "sha256:cae2e2439cb88853e421901ec040a758960b576126dab520fa08e9de431d1bef"}, ] [[package]] @@ -555,4 +596,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "6f6c191c1028d17a97fdfa84cedfd3cef94b5d63d98b8c1d333b3398eeea9055" +content-hash = "bcf31a142c86d9e556553c8c260a93b563ac64a043076dbd48b26111d422c26e" diff --git a/pyproject.toml b/pyproject.toml index 66a8846..bec7144 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,7 @@ +[project] +name = "webflow" +dynamic = ["version"] + [tool.poetry] name = "webflow" version = "1.2.1" @@ -5,7 +9,7 @@ description = "" readme = "README.md" authors = [] keywords = [] - +license = "MIT" classifiers = [ "Intended Audience :: Developers", "Programming Language :: Python", @@ -15,35 +19,40 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.15", "Operating System :: OS Independent", "Operating System :: POSIX", "Operating System :: MacOS", "Operating System :: POSIX :: Linux", "Operating System :: Microsoft :: Windows", "Topic :: Software Development :: Libraries :: Python Modules", - "Typing :: Typed" + "Typing :: Typed", + "License :: OSI Approved :: MIT License" ] packages = [ { include = "webflow", from = "src"} ] -[project.urls] +[tool.poetry.urls] Repository = 'https://github.com/webflow/webflow-python' [tool.poetry.dependencies] python = "^3.8" httpx = ">=0.21.2" pydantic = ">= 1.9.2" -pydantic-core = "^2.18.2" +pydantic-core = ">=2.18.2" typing_extensions = ">= 4.0.0" -[tool.poetry.dev-dependencies] -mypy = "1.0.1" +[tool.poetry.group.dev.dependencies] +mypy = "==1.13.0" pytest = "^7.4.0" pytest-asyncio = "^0.23.5" +pytest-xdist = "^3.6.1" python-dateutil = "^2.9.0" types-python-dateutil = "^2.9.0.20240316" -ruff = "^0.5.6" +ruff = "==0.11.5" [tool.pytest.ini_options] testpaths = [ "tests" ] @@ -55,6 +64,26 @@ plugins = ["pydantic.mypy"] [tool.ruff] line-length = 120 +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "F", # pyflakes + "I", # isort +] +ignore = [ + "E402", # Module level import not at top of file + "E501", # Line too long + "E711", # Comparison to `None` should be `cond is not None` + "E712", # Avoid equality comparisons to `True`; use `if ...:` checks + "E721", # Use `is` and `is not` for type comparisons, or `isinstance()` for insinstance checks + "E722", # Do not use bare `except` + "E731", # Do not assign a `lambda` expression, use a `def` + "F821", # Undefined name + "F841" # Local variable ... is assigned to but never used +] + +[tool.ruff.lint.isort] +section-order = ["future", "standard-library", "third-party", "first-party"] [build-system] requires = ["poetry-core"] diff --git a/reference.md b/reference.md index 9abecdf..fbfbd16 100644 --- a/reference.md +++ b/reference.md @@ -1,6 +1,6 @@ # Reference ## Token -
client.token.authorized_by() +
client.token.authorized_by() -> AuthorizedUser
@@ -30,10 +30,13 @@ Required Scope | `authorized_user:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.token.authorized_by() ``` @@ -62,7 +65,7 @@ client.token.authorized_by()
-
client.token.introspect() +
client.token.introspect() -> Authorization
@@ -92,10 +95,13 @@ Information about the authorization token ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.token.introspect() ``` @@ -125,7 +131,7 @@ client.token.introspect()
## Sites -
client.sites.create(...) +
client.sites.create(...) -> Site
@@ -137,7 +143,7 @@ client.token.introspect()
-Create a site. +Create a site. This endpoint requires an Enterprise workspace. @@ -157,13 +163,16 @@ Required scope | `workspace:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.create( workspace_id="580e63e98c9a982ac9b8b741", - name="The Hitchhiker's Guide to the Galaxy", + name="The Hitchhiker\'s Guide to the Galaxy", ) ``` @@ -224,7 +233,7 @@ client.sites.create(
-
client.sites.list() +
client.sites.list() -> Sites
@@ -254,10 +263,13 @@ Required scope | `sites:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.list() ``` @@ -286,7 +298,7 @@ client.sites.list()
-
client.sites.get(...) +
client.sites.get(...) -> Site
@@ -316,10 +328,13 @@ Required scope | `sites:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.get( site_id="580e63e98c9a982ac9b8b741", ) @@ -358,7 +373,7 @@ client.sites.get(
-
client.sites.delete(...) +
client.sites.delete(...)
@@ -370,7 +385,7 @@ client.sites.get(
-Delete a site. +Delete a site. This endpoint requires an Enterprise workspace. @@ -390,10 +405,13 @@ Required scope | `sites:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.delete( site_id="580e63e98c9a982ac9b8b741", ) @@ -432,7 +450,7 @@ client.sites.delete(
-
client.sites.update(...) +
client.sites.update(...) -> Site
@@ -444,7 +462,7 @@ client.sites.delete(
-Update a site. +Update a site. This endpoint requires an Enterprise workspace. @@ -464,10 +482,13 @@ Required scope | `sites:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.update( site_id="580e63e98c9a982ac9b8b741", ) @@ -522,7 +543,7 @@ client.sites.update(
-
client.sites.get_custom_domain(...) +
client.sites.get_custom_domain(...) -> Domains
@@ -552,10 +573,13 @@ Required scope | `sites:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.get_custom_domain( site_id="580e63e98c9a982ac9b8b741", ) @@ -594,7 +618,7 @@ client.sites.get_custom_domain(
-
client.sites.publish(...) +
client.sites.publish(...) -> SitesPublishResponse
@@ -606,7 +630,7 @@ client.sites.get_custom_domain(
-Publishes a site to one or more more domains. +Publishes a site to one or more more domains. To publish to a specific custom domain, use the domain IDs from the [Get Custom Domains](/data/reference/sites/get-custom-domain) endpoint. @@ -628,13 +652,19 @@ Required scope | `sites:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.publish( site_id="580e63e98c9a982ac9b8b741", - custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], + custom_domains=[ + "660c6449dd97ebc7346ac629", + "660c6449dd97ebc7346ac62f" + ], publish_to_webflow_subdomain=False, ) @@ -660,7 +690,7 @@ client.sites.publish(
-**custom_domains:** `typing.Optional[typing.Sequence[str]]` — Array of Custom Domain IDs to publish +**custom_domains:** `typing.Optional[typing.List[str]]` — Array of Custom Domain IDs to publish
@@ -689,7 +719,7 @@ client.sites.publish(
## Collections -
client.collections.list(...) +
client.collections.list(...) -> CollectionList
@@ -719,10 +749,13 @@ Required scope | `cms:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.list( site_id="580e63e98c9a982ac9b8b741", ) @@ -761,7 +794,7 @@ client.collections.list(
-
client.collections.create(...) +
client.collections.create(...) -> Collection
@@ -792,11 +825,14 @@ Required scope | `cms:write`
```python -from webflow import ReferenceField, ReferenceFieldMetadata, StaticField, Webflow +from webflow import Webflow, StaticField +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.create( site_id="580e63e98c9a982ac9b8b741", display_name="Blog Posts", @@ -815,15 +851,12 @@ client.collections.create( display_name="Content", help_text="The content of the blog post", ), - ReferenceField( + StaticField( is_required=True, - type="Reference", + type=, display_name="Author", help_text="The author of the blog post", - metadata=ReferenceFieldMetadata( - collection_id="23cc2d952d4e4631ffd4345d2743db4e", - ), - ), + ) ], ) @@ -873,7 +906,7 @@ client.collections.create(
-**fields:** `typing.Optional[typing.Sequence[FieldCreate]]` — An array of custom fields to add to the collection +**fields:** `typing.Optional[typing.List[FieldCreate]]` — An array of custom fields to add to the collection
@@ -893,7 +926,7 @@ client.collections.create(
-
client.collections.get(...) +
client.collections.get(...) -> Collection
@@ -923,10 +956,13 @@ Required scope | `cms:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.get( collection_id="580e63fc8c9a982ac9b8b745", ) @@ -965,7 +1001,7 @@ client.collections.get(
-
client.collections.delete(...) +
client.collections.delete(...)
@@ -995,10 +1031,13 @@ Required scope | `cms:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.delete( collection_id="580e63fc8c9a982ac9b8b745", ) @@ -1038,7 +1077,7 @@ client.collections.delete(
## Pages -
client.pages.list(...) +
client.pages.list(...) -> PageList
@@ -1068,10 +1107,13 @@ Required scope | `pages:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.pages.list( site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0", @@ -1141,7 +1183,7 @@ Unique identifier for a specific Locale.
-
client.pages.get_metadata(...) +
client.pages.get_metadata(...) -> Page
@@ -1171,10 +1213,13 @@ Required scope | `pages:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.pages.get_metadata( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", @@ -1226,7 +1271,7 @@ Unique identifier for a specific Locale.
-
client.pages.update_page_settings(...) +
client.pages.update_page_settings(...) -> Page
@@ -1256,21 +1301,21 @@ Required scope | `pages:write` ```python from webflow import Webflow -from webflow.resources.pages import ( - PageMetadataWriteOpenGraph, - PageMetadataWriteSeo, -) +from webflow.environment import WebflowEnvironment +from webflow.pages import PageMetadataWriteSeo, PageMetadataWriteOpenGraph client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.pages.update_page_settings( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", title="Guide to the Galaxy", slug="guide-to-the-galaxy", seo=PageMetadataWriteSeo( - title="The Ultimate Hitchhiker's Guide to the Galaxy", + title="The Ultimate Hitchhiker\'s Guide to the Galaxy", description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", ), open_graph=PageMetadataWriteOpenGraph( @@ -1325,7 +1370,7 @@ Unique identifier for a specific Locale. **slug:** `typing.Optional[str]` -Slug for the page. +Slug for the page. **Note:** Updating slugs in secondary locales is only supported in Advanced and Enterprise localization add-on plans. @@ -1364,7 +1409,7 @@ Slug for the page.
-
client.pages.get_content(...) +
client.pages.get_content(...) -> Dom
@@ -1378,7 +1423,7 @@ Slug for the page. Get text and component instance content from a static page. -Localization +Localization Required scope | `pages:read`
@@ -1396,10 +1441,13 @@ Required scope | `pages:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.pages.get_content( page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", @@ -1469,7 +1517,7 @@ Unique identifier for a specific Locale.
-
client.pages.update_static_content(...) +
client.pages.update_static_content(...) -> UpdateStaticContentResponse
@@ -1507,67 +1555,38 @@ Required scope | `pages:write`
```python -from webflow import ( - ComponentInstanceNodePropertyOverridesWrite, - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, - Select, - SelectNodeWriteChoicesItem, - SubmitButtonNodeWrite, - TextInputNodeWrite, - TextNodeWrite, - Webflow, -) +from webflow import Webflow, TextNodeWrite +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.pages.update_static_content( page_id="63c720f9347c2139b248e552", locale_id="localeId", nodes=[ TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", - text="

The Hitchhiker's Guide to the Galaxy

", + text="

The Hitchhiker\'s Guide to the Galaxy

", ), TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", - text="

Don't Panic!

Always know where your towel is.

", + text="

Don\'t Panic!

Always know where your towel is.

", ), - Select( + TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", - choices=[ - SelectNodeWriteChoicesItem( - value="choice-1", - text="First choice", - ), - SelectNodeWriteChoicesItem( - value="choice-2", - text="Second choice", - ), - ], ), - TextInputNodeWrite( + TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", - placeholder="Enter something here...", ), - SubmitButtonNodeWrite( + TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", - value="Submit", - waiting_text="Submitting...", ), - ComponentInstanceNodePropertyOverridesWrite( + TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", - property_overrides=[ - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", - text="

Time is an illusion

", - ), - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", - text="Life, the Universe and Everything", - ), - ], - ), + ) ], ) @@ -1601,7 +1620,7 @@ client.pages.update_static_content(
-**nodes:** `typing.Sequence[PageDomWriteNodesItem]` — List of DOM Nodes with the new content that will be updated in each node. +**nodes:** `typing.List[PageDomWriteNodesItem]` — List of DOM Nodes with the new content that will be updated in each node.
@@ -1622,7 +1641,7 @@ client.pages.update_static_content(
## Components -
client.components.list(...) +
client.components.list(...) -> ComponentList
@@ -1652,10 +1671,13 @@ Required scope | `components:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.components.list( site_id="580e63e98c9a982ac9b8b741", branch_id="68026fa68ef6dc744c75b833", @@ -1721,7 +1743,7 @@ client.components.list(
-
client.components.get_content(...) +
client.components.get_content(...) -> ComponentDom
@@ -1754,10 +1776,13 @@ Required scope | `components:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.components.get_content( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", @@ -1845,7 +1870,7 @@ Unique identifier for a specific Locale.
-
client.components.update_content(...) +
client.components.update_content(...) -> ComponentsUpdateContentResponse
@@ -1883,20 +1908,14 @@ Required scope | `components:write`
```python -from webflow import ( - ComponentInstanceNodePropertyOverridesWrite, - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, - Select, - SelectNodeWriteChoicesItem, - SubmitButtonNodeWrite, - TextInputNodeWrite, - TextNodeWrite, - Webflow, -) +from webflow import Webflow, TextNodeWrite +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.components.update_content( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", @@ -1905,47 +1924,24 @@ client.components.update_content( nodes=[ TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", - text="

The Hitchhiker's Guide to the Galaxy

", + text="

The Hitchhiker\'s Guide to the Galaxy

", ), TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", - text="

Don't Panic!

Always know where your towel is.

", + text="

Don\'t Panic!

Always know where your towel is.

", ), - Select( + TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", - choices=[ - SelectNodeWriteChoicesItem( - value="choice-1", - text="First choice", - ), - SelectNodeWriteChoicesItem( - value="choice-2", - text="Second choice", - ), - ], ), - TextInputNodeWrite( + TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", - placeholder="Enter something here...", ), - SubmitButtonNodeWrite( + TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", - value="Submit", - waiting_text="Submitting...", ), - ComponentInstanceNodePropertyOverridesWrite( + TextNodeWrite( node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", - property_overrides=[ - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", - text="

Time is an illusion

", - ), - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", - text="Life, the Universe and Everything", - ), - ], - ), + ) ], ) @@ -1979,7 +1975,7 @@ client.components.update_content(
-**nodes:** `typing.Sequence[ComponentDomWriteNodesItem]` — List of DOM Nodes with the new content that will be updated in each node. +**nodes:** `typing.List[ComponentDomWriteNodesItem]` — List of DOM Nodes with the new content that will be updated in each node.
@@ -2019,7 +2015,7 @@ Unique identifier for a specific Locale.
-
client.components.get_properties(...) +
client.components.get_properties(...) -> ComponentProperties
@@ -2051,10 +2047,13 @@ Required scope | `components:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.components.get_properties( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", @@ -2142,7 +2141,7 @@ Unique identifier for a specific Locale.
-
client.components.update_properties(...) +
client.components.update_properties(...) -> ComponentsUpdatePropertiesResponse
@@ -2178,11 +2177,14 @@ Required scope | `components:write` ```python from webflow import Webflow -from webflow.resources.components import ComponentPropertiesWritePropertiesItem +from webflow.environment import WebflowEnvironment +from webflow.components import ComponentPropertiesWritePropertiesItem client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.components.update_properties( site_id="580e63e98c9a982ac9b8b741", component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", @@ -2196,7 +2198,7 @@ client.components.update_properties( ComponentPropertiesWritePropertiesItem( property_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", text="

Dont Panic!

Always know where your towel is.

", - ), + ) ], ) @@ -2230,7 +2232,7 @@ client.components.update_properties(
-**properties:** `typing.Sequence[ComponentPropertiesWritePropertiesItem]` — A list of component properties to update within the specified secondary locale. +**properties:** `typing.List[ComponentPropertiesWritePropertiesItem]` — A list of component properties to update within the specified secondary locale.
@@ -2271,7 +2273,7 @@ Unique identifier for a specific Locale.
## Scripts -
client.scripts.list(...) +
client.scripts.list(...) -> RegisteredScriptList
@@ -2305,10 +2307,13 @@ Required scope | `custom_code:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.scripts.list( site_id="580e63e98c9a982ac9b8b741", ) @@ -2347,7 +2352,7 @@ client.scripts.list(
-
client.scripts.register_hosted(...) +
client.scripts.register_hosted(...) -> CustomCodeHostedResponse
@@ -2381,10 +2386,13 @@ Required scope | `custom_code:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.scripts.register_hosted( site_id="580e63e98c9a982ac9b8b741", hosted_location="hostedLocation", @@ -2467,7 +2475,7 @@ client.scripts.register_hosted(
-
client.scripts.register_inline(...) +
client.scripts.register_inline(...) -> CustomCodeInlineResponse
@@ -2501,13 +2509,16 @@ Required scope | `custom_code:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.scripts.register_inline( site_id="580e63e98c9a982ac9b8b741", - source_code="alert('hello world');", + source_code="alert(\'hello world\');", version="0.0.1", display_name="Alert", ) @@ -2587,7 +2598,7 @@ client.scripts.register_inline(
## Assets -
client.assets.list(...) +
client.assets.list(...) -> Assets
@@ -2617,10 +2628,13 @@ Required scope | `assets:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.assets.list( site_id="580e63e98c9a982ac9b8b741", offset=1, @@ -2677,7 +2691,7 @@ client.assets.list(
-
client.assets.create(...) +
client.assets.create(...) -> AssetUpload
@@ -2689,7 +2703,7 @@ client.assets.list(
-The first step in uploading an asset to a site. +The first step in uploading an asset to a site. This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. @@ -2699,7 +2713,7 @@ Use these properties in the header of a [POST request to Amazson s3](https://doc To learn more about how to upload assets to Webflow, see our [assets guide](/data/docs/working-with-assets). - + Required scope | `assets:write`
@@ -2716,10 +2730,13 @@ To learn more about how to upload assets to Webflow, see our [assets guide](/dat ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.assets.create( site_id="580e63e98c9a982ac9b8b741", file_name="file.png", @@ -2784,7 +2801,7 @@ client.assets.create(
-
client.assets.get(...) +
client.assets.get(...) -> Asset
@@ -2814,10 +2831,13 @@ Required scope | `assets:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.assets.get( asset_id="580e63fc8c9a982ac9b8b745", ) @@ -2856,7 +2876,7 @@ client.assets.get(
-
client.assets.delete(...) +
client.assets.delete(...)
@@ -2886,10 +2906,13 @@ Required Scope: `assets: write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.assets.delete( asset_id="580e63fc8c9a982ac9b8b745", ) @@ -2928,7 +2951,7 @@ client.assets.delete(
-
client.assets.update(...) +
client.assets.update(...) -> Asset
@@ -2958,10 +2981,13 @@ Required scope | `assets:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.assets.update( asset_id="580e63fc8c9a982ac9b8b745", ) @@ -3016,7 +3042,7 @@ client.assets.update(
-
client.assets.list_folders(...) +
client.assets.list_folders(...) -> AssetFolderList
@@ -3046,10 +3072,13 @@ Required scope | `assets:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.assets.list_folders( site_id="580e63e98c9a982ac9b8b741", ) @@ -3088,7 +3117,7 @@ client.assets.list_folders(
-
client.assets.create_folder(...) +
client.assets.create_folder(...) -> AssetFolder
@@ -3118,10 +3147,13 @@ Required scope | `assets:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.assets.create_folder( site_id="580e63e98c9a982ac9b8b741", display_name="my asset folder", @@ -3177,7 +3209,7 @@ client.assets.create_folder(
-
client.assets.get_folder(...) +
client.assets.get_folder(...) -> AssetFolder
@@ -3207,10 +3239,13 @@ Required scope | `assets:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.assets.get_folder( asset_folder_id="6390c49774a71f0e3c1a08ee", ) @@ -3250,7 +3285,7 @@ client.assets.get_folder(
## Webhooks -
client.webhooks.list(...) +
client.webhooks.list(...) -> WebhookList
@@ -3280,10 +3315,13 @@ Required scope | `sites:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.webhooks.list( site_id="580e63e98c9a982ac9b8b741", ) @@ -3322,7 +3360,7 @@ client.webhooks.list(
-
client.webhooks.create(...) +
client.webhooks.create(...) -> Webhook
@@ -3354,13 +3392,15 @@ Required scope | `sites:write`
```python -import datetime - from webflow import Webflow +from webflow.environment import WebflowEnvironment +import datetime client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.webhooks.create( site_id_="580e63e98c9a982ac9b8b741", id="582266e0cd48de0f0e3c6d8b", @@ -3368,12 +3408,8 @@ client.webhooks.create( url="https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", workspace_id="4f4e46fd476ea8c507000001", site_id="562ac0395358780a1f5e6fbd", - last_triggered=datetime.datetime.fromisoformat( - "2023-02-08 23:59:28+00:00", - ), - created_on=datetime.datetime.fromisoformat( - "2022-11-08 23:59:28+00:00", - ), + last_triggered=datetime.datetime.fromisoformat("2023-02-08T23:59:28+00:00"), + created_on=datetime.datetime.fromisoformat("2022-11-08T23:59:28+00:00"), ) ``` @@ -3390,63 +3426,7 @@ client.webhooks.create(
-**site_id_:** `str` — Unique identifier for a Site - -
-
- -
-
- -**id:** `typing.Optional[str]` — Unique identifier for the Webhook registration - -
-
- -
-
- -**trigger_type:** `typing.Optional[TriggerType]` - -
-
- -
-
- -**url:** `typing.Optional[str]` — URL to send the Webhook payload to - -
-
- -
-
- -**workspace_id:** `typing.Optional[str]` — Unique identifier for the Workspace the Webhook is registered in - -
-
- -
-
- -**site_id:** `typing.Optional[str]` — Unique identifier for the Site the Webhook is registered in - -
-
- -
-
- -**filter:** `typing.Optional[WebhookFilter]` — Only supported for the `form_submission` trigger type. Filter for the form you want Webhooks to be sent for. - -
-
- -
-
- -**last_triggered:** `typing.Optional[dt.datetime]` — Date the Webhook instance was last triggered +**site_id:** `str` — Unique identifier for a Site
@@ -3454,7 +3434,7 @@ client.webhooks.create(
-**created_on:** `typing.Optional[dt.datetime]` — Date the Webhook registration was created +**request:** `Webhook`
@@ -3474,7 +3454,7 @@ client.webhooks.create(
-
client.webhooks.get(...) +
client.webhooks.get(...) -> Webhook
@@ -3504,10 +3484,13 @@ Required scope: `sites:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.webhooks.get( webhook_id="580e64008c9a982ac9b8b754", ) @@ -3546,7 +3529,7 @@ client.webhooks.get(
-
client.webhooks.delete(...) +
client.webhooks.delete(...)
@@ -3576,10 +3559,13 @@ Required scope: `sites:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.webhooks.delete( webhook_id="580e64008c9a982ac9b8b754", ) @@ -3619,7 +3605,7 @@ client.webhooks.delete(
## Forms -
client.forms.list(...) +
client.forms.list(...) -> FormList
@@ -3649,10 +3635,13 @@ Required scope | `forms:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.forms.list( site_id="580e63e98c9a982ac9b8b741", limit=1, @@ -3709,7 +3698,7 @@ client.forms.list(
-
client.forms.get(...) +
client.forms.get(...) -> Form
@@ -3739,10 +3728,13 @@ Required scope | `forms:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.forms.get( form_id="580e63e98c9a982ac9b8b741", ) @@ -3781,7 +3773,7 @@ client.forms.get(
-
client.forms.list_submissions(...) +
client.forms.list_submissions(...) -> FormSubmissionList
@@ -3797,7 +3789,7 @@ List form submissions for a given form When a form is used in a component definition, each instance of the form is considered a unique form. - + To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. @@ -3817,10 +3809,13 @@ Required scope | `forms:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.forms.list_submissions( form_id="580e63e98c9a982ac9b8b741", offset=1, @@ -3877,7 +3872,7 @@ client.forms.list_submissions(
-
client.forms.get_submission(...) +
client.forms.get_submission(...) -> FormSubmission
@@ -3907,10 +3902,13 @@ Required scope | `forms:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.forms.get_submission( form_submission_id="580e63e98c9a982ac9b8b741", ) @@ -3949,7 +3947,7 @@ client.forms.get_submission(
-
client.forms.delete_submission(...) +
client.forms.delete_submission(...)
@@ -3980,10 +3978,13 @@ Required scope | `forms:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.forms.delete_submission( form_submission_id="580e63e98c9a982ac9b8b741", ) @@ -4022,7 +4023,7 @@ client.forms.delete_submission(
-
client.forms.update_submission(...) +
client.forms.update_submission(...) -> FormSubmission
@@ -4052,10 +4053,13 @@ Required scope | `forms:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.forms.update_submission( form_submission_id="580e63e98c9a982ac9b8b741", ) @@ -4082,7 +4086,7 @@ client.forms.update_submission(
-**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set +**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Any]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set
@@ -4103,7 +4107,7 @@ client.forms.update_submission(
## Products -
client.products.list(...) +
client.products.list(...) -> ProductAndSkUsList
@@ -4115,7 +4119,7 @@ client.forms.update_submission(
-Retrieve all products for a site. +Retrieve all products for a site. Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. @@ -4136,10 +4140,13 @@ Required scope | `ecommerce:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.products.list( site_id="580e63e98c9a982ac9b8b741", offset=1, @@ -4196,7 +4203,7 @@ client.products.list(
-
client.products.create(...) +
client.products.create(...) -> ProductAndSkUs
@@ -4232,22 +4239,15 @@ Required scope | `ecommerce:write`
```python -from webflow import ( - ProductFieldData, - SkuFieldData, - SkuFieldDataPrice, - SkuPropertyList, - SkuPropertyListEnumItem, - Webflow, -) -from webflow.resources.products import ( - ProductSkuCreateProduct, - ProductSkuCreateSku, -) +from webflow import Webflow, ProductFieldData, SkuPropertyList, SkuPropertyListEnumItem, SkuFieldData, SkuFieldDataPrice +from webflow.environment import WebflowEnvironment +from webflow.products import ProductSkuCreateProduct, ProductSkuCreateSku client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.products.create( site_id="580e63e98c9a982ac9b8b741", publish_status="staging", @@ -4275,7 +4275,7 @@ client.products.create( id="blue", name="Blue", slug="blue", - ), + ) ], ), SkuPropertyList( @@ -4296,9 +4296,9 @@ client.products.create( id="large", name="Large", slug="large", - ), + ) ], - ), + ) ], ), ), @@ -4307,7 +4307,7 @@ client.products.create( name="Colorful T-shirt - Red Small", slug="colorful-t-shirt-red-small", price=SkuFieldDataPrice( - value=2499.0, + value=2499, unit="USD", currency="USD", ), @@ -4374,7 +4374,7 @@ client.products.create(
-
client.products.get(...) +
client.products.get(...) -> ProductAndSkUs
@@ -4405,10 +4405,13 @@ Required scope | `ecommerce:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.products.get( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", @@ -4456,7 +4459,7 @@ client.products.get(
-
client.products.update(...) +
client.products.update(...) -> Product
@@ -4488,10 +4491,13 @@ Required scope | `ecommerce:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.products.update( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", @@ -4563,7 +4569,7 @@ client.products.update(
-
client.products.create_sku(...) +
client.products.create_sku(...) -> ProductsCreateSkuResponse
@@ -4594,13 +4600,15 @@ Required scope | `ecommerce:write`
```python +from webflow import Webflow, Sku, SkuFieldData, SkuFieldDataPrice +from webflow.environment import WebflowEnvironment import datetime -from webflow import Sku, SkuFieldData, SkuFieldDataPrice, Webflow - client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.products.create_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", @@ -4608,20 +4616,14 @@ client.products.create_sku( Sku( id="66072fb71b89448912e2681c", cms_locale_id="653ad57de882f528b32e810e", - last_published=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - created_on=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), + last_published=datetime.datetime.fromisoformat("2023-03-17T18:47:35+00:00"), + last_updated=datetime.datetime.fromisoformat("2023-03-17T18:47:35+00:00"), + created_on=datetime.datetime.fromisoformat("2023-03-17T18:47:35+00:00"), field_data=SkuFieldData( name="Colorful T-shirt - Default", slug="colorful-t-shirt-default", price=SkuFieldDataPrice( - value=2499.0, + value=2499, unit="USD", currency="USD", ), @@ -4660,7 +4662,7 @@ client.products.create_sku(
-**skus:** `typing.Sequence[Sku]` — An array of the SKU data your are adding +**skus:** `typing.List[Sku]` — An array of the SKU data your are adding
@@ -4688,7 +4690,7 @@ client.products.create_sku(
-
client.products.update_sku(...) +
client.products.update_sku(...) -> Sku
@@ -4719,13 +4721,15 @@ Required scope | `ecommerce:write`
```python +from webflow import Webflow, Sku, SkuFieldData, SkuFieldDataPrice +from webflow.environment import WebflowEnvironment import datetime -from webflow import Sku, SkuFieldData, SkuFieldDataPrice, Webflow - client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.products.update_sku( site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745", @@ -4733,20 +4737,14 @@ client.products.update_sku( sku=Sku( id="66072fb71b89448912e2681c", cms_locale_id="653ad57de882f528b32e810e", - last_published=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - last_updated=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), - created_on=datetime.datetime.fromisoformat( - "2023-03-17 18:47:35+00:00", - ), + last_published=datetime.datetime.fromisoformat("2023-03-17T18:47:35+00:00"), + last_updated=datetime.datetime.fromisoformat("2023-03-17T18:47:35+00:00"), + created_on=datetime.datetime.fromisoformat("2023-03-17T18:47:35+00:00"), field_data=SkuFieldData( name="Colorful T-shirt - Default", slug="colorful-t-shirt-default", price=SkuFieldDataPrice( - value=2499.0, + value=2499, unit="USD", currency="USD", ), @@ -4821,7 +4819,7 @@ client.products.update_sku(
## Orders -
client.orders.list(...) +
client.orders.list(...) -> OrderList
@@ -4851,10 +4849,13 @@ Required scope | `ecommerce:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.orders.list( site_id="580e63e98c9a982ac9b8b741", status="pending", @@ -4920,7 +4921,7 @@ client.orders.list(
-
client.orders.get(...) +
client.orders.get(...) -> Order
@@ -4951,10 +4952,13 @@ Required scope | `ecommerce:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.orders.get( site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415", @@ -5002,7 +5006,7 @@ client.orders.get(
-
client.orders.update(...) +
client.orders.update(...) -> Order
@@ -5034,10 +5038,13 @@ Required scope | `ecommerce:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.orders.update( site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415", @@ -5117,7 +5124,7 @@ client.orders.update(
-
client.orders.update_fulfill(...) +
client.orders.update_fulfill(...) -> Order
@@ -5147,10 +5154,13 @@ Required scope | `ecommerce:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.orders.update_fulfill( site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415", @@ -5206,7 +5216,7 @@ client.orders.update_fulfill(
-
client.orders.update_unfulfill(...) +
client.orders.update_unfulfill(...) -> Order
@@ -5236,10 +5246,13 @@ Required scope | `ecommerce:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.orders.update_unfulfill( site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415", @@ -5287,7 +5300,7 @@ client.orders.update_unfulfill(
-
client.orders.refund(...) +
client.orders.refund(...) -> Order
@@ -5318,10 +5331,13 @@ Required scope | `ecommerce:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.orders.refund( site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415", @@ -5378,7 +5394,7 @@ client.orders.refund(
## Inventory -
client.inventory.list(...) +
client.inventory.list(...) -> InventoryItem
@@ -5408,10 +5424,13 @@ Required scope | `ecommerce:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.inventory.list( sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415", @@ -5459,7 +5478,7 @@ client.inventory.list(
-
client.inventory.update(...) +
client.inventory.update(...) -> InventoryItem
@@ -5471,10 +5490,10 @@ client.inventory.list(
-Updates the current inventory levels for a particular SKU item. +Updates the current inventory levels for a particular SKU item. -Updates may be given in one or two methods, absolutely or incrementally. -- Absolute updates are done by setting `quantity` directly. +Updates may be given in one or two methods, absolutely or incrementally. +- Absolute updates are done by setting `quantity` directly. - Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. Required scope | `ecommerce:write` @@ -5493,10 +5512,13 @@ Required scope | `ecommerce:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.inventory.update( sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415", @@ -5570,7 +5592,7 @@ client.inventory.update(
## Ecommerce -
client.ecommerce.get_settings(...) +
client.ecommerce.get_settings(...) -> EcommerceSettings
@@ -5600,10 +5622,13 @@ Required scope | `ecommerce:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.ecommerce.get_settings( site_id="580e63e98c9a982ac9b8b741", ) @@ -5643,7 +5668,7 @@ client.ecommerce.get_settings(
## Collections Fields -
client.collections.fields.create(...) +
client.collections.fields.create(...) -> FieldCreate
@@ -5676,23 +5701,23 @@ Required scope | `cms:write`
```python -from webflow import ReferenceField, ReferenceFieldMetadata, Webflow +from webflow import Webflow, StaticField +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.fields.create( collection_id="580e63fc8c9a982ac9b8b745", - request=ReferenceField( - id="562ac0395358780a1f5e6fbd", + request=StaticField( + id="562ac0395358780a1f5e6fbc", is_editable=True, is_required=False, - type="Reference", - display_name="Author", - help_text="Add the post author here", - metadata=ReferenceFieldMetadata( - collection_id="63692ab61fb2852f582ba8f5", - ), + type="RichText", + display_name="Post Body", + help_text="Add the body of your post here", ), ) @@ -5738,7 +5763,7 @@ client.collections.fields.create(
-
client.collections.fields.delete(...) +
client.collections.fields.delete(...)
@@ -5768,10 +5793,13 @@ Required scope | `cms:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.fields.delete( collection_id="580e63fc8c9a982ac9b8b745", field_id="580e63fc8c9a982ac9b8b745", @@ -5819,7 +5847,7 @@ client.collections.fields.delete(
-
client.collections.fields.update(...) +
client.collections.fields.update(...) -> Field
@@ -5849,10 +5877,13 @@ Required scope | `cms:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.fields.update( collection_id="580e63fc8c9a982ac9b8b745", field_id="580e63fc8c9a982ac9b8b745", @@ -5928,7 +5959,7 @@ client.collections.fields.update(
## Collections Items -
client.collections.items.list_items(...) +
client.collections.items.list_items(...) -> CollectionItemList
@@ -5958,10 +5989,13 @@ Required scope | `CMS:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.list_items( collection_id="580e63fc8c9a982ac9b8b745", cms_locale_id="cmsLocaleId", @@ -6071,7 +6105,7 @@ client.collections.items.list_items(
-
client.collections.items.create_item(...) +
client.collections.items.create_item(...) -> CollectionItem
@@ -6103,38 +6137,24 @@ Required scope | `CMS:write`
```python -from webflow import ( - CollectionItemPostSingle, - CollectionItemPostSingleFieldData, - Webflow, -) -from webflow.resources.collections.resources.items import MultipleItems +from webflow import Webflow, CollectionItemPostSingle, CollectionItemPostSingleFieldData +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.create_item( collection_id="580e63fc8c9a982ac9b8b745", skip_invalid_files=True, - request=MultipleItems( - items=[ - CollectionItemPostSingle( - is_archived=False, - is_draft=False, - field_data=CollectionItemPostSingleFieldData( - name="Senior Data Analyst", - slug="senior-data-analyst", - ), - ), - CollectionItemPostSingle( - is_archived=False, - is_draft=False, - field_data=CollectionItemPostSingleFieldData( - name="Product Manager", - slug="product-manager", - ), - ), - ], + request=CollectionItemPostSingle( + is_archived=False, + is_draft=False, + field_data=CollectionItemPostSingleFieldData( + name="The Hitchhiker\'s Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", + ), ), ) @@ -6188,7 +6208,7 @@ client.collections.items.create_item(
-
client.collections.items.delete_items(...) +
client.collections.items.delete_items(...)
@@ -6220,13 +6240,14 @@ Required scope | `CMS:write` ```python from webflow import Webflow -from webflow.resources.collections.resources.items import ( - ItemsDeleteItemsRequestItemsItem, -) +from webflow.environment import WebflowEnvironment +from webflow.collections.items import ItemsDeleteItemsRequestItemsItem client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.delete_items( collection_id="580e63fc8c9a982ac9b8b745", items=[ @@ -6258,7 +6279,7 @@ client.collections.items.delete_items(
-**items:** `typing.Sequence[ItemsDeleteItemsRequestItemsItem]` +**items:** `typing.List[ItemsDeleteItemsRequestItemsItem]`
@@ -6278,7 +6299,7 @@ client.collections.items.delete_items(
-
client.collections.items.update_items(...) +
client.collections.items.update_items(...) -> ItemsUpdateItemsResponse
@@ -6311,37 +6332,50 @@ Required scope | `CMS:write`
```python -from webflow import ( - CollectionItemWithIdInput, - CollectionItemWithIdInputFieldData, - Webflow, -) +from webflow import Webflow, CollectionItemWithIdInput, CollectionItemWithIdInputFieldData +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.update_items( collection_id="580e63fc8c9a982ac9b8b745", skip_invalid_files=True, items=[ CollectionItemWithIdInput( - id="580e64008c9a982ac9b8b754", - is_archived=False, - is_draft=False, + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca5", + field_data=CollectionItemWithIdInputFieldData( + name="Ne Paniquez Pas", + slug="ne-paniquez-pas", + ), + ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5ea6", + cms_locale_id="66f6e966c9e1dc700a857ca4", field_data=CollectionItemWithIdInputFieldData( - name="Senior Data Analyst", - slug="senior-data-analyst", + name="No Entrar en Pánico", + slug="no-entrar-en-panico", ), ), CollectionItemWithIdInput( - id="580e64008c9a982ac9b8b754", - is_archived=False, - is_draft=False, + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca5", field_data=CollectionItemWithIdInputFieldData( - name="Product Manager", - slug="product-manager", + name="Au Revoir et Merci pour Tous les Poissons", + slug="au-revoir-et-merci", ), ), + CollectionItemWithIdInput( + id="66f6ed9576ddacf3149d5eaa", + cms_locale_id="66f6e966c9e1dc700a857ca4", + field_data=CollectionItemWithIdInputFieldData( + name="Hasta Luego y Gracias por Todo el Pescado", + slug="hasta-luego-y-gracias", + ), + ) ], ) @@ -6375,7 +6409,7 @@ client.collections.items.update_items(
-**items:** `typing.Optional[typing.Sequence[CollectionItemWithIdInput]]` +**items:** `typing.Optional[typing.List[CollectionItemWithIdInput]]`
@@ -6395,7 +6429,7 @@ client.collections.items.update_items(
-
client.collections.items.list_items_live(...) +
client.collections.items.list_items_live(...) -> CollectionItemList
@@ -6429,10 +6463,13 @@ Required scope | `CMS:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.list_items_live( collection_id="580e63fc8c9a982ac9b8b745", cms_locale_id="cmsLocaleId", @@ -6542,7 +6579,7 @@ client.collections.items.list_items_live(
-
client.collections.items.create_item_live(...) +
client.collections.items.create_item_live(...) -> CollectionItem
@@ -6575,34 +6612,24 @@ Required scope | `CMS:write`
```python -from webflow import CollectionItem, CollectionItemFieldData, Webflow -from webflow.resources.collections.resources.items import MultipleLiveItems +from webflow import Webflow, CollectionItem, CollectionItemFieldData +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.create_item_live( collection_id="580e63fc8c9a982ac9b8b745", skip_invalid_files=True, - request=MultipleLiveItems( - items=[ - CollectionItem( - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Senior Data Analyst", - slug="senior-data-analyst", - ), - ), - CollectionItem( - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="Product Manager", - slug="product-manager", - ), - ), - ], + request=CollectionItem( + is_archived=False, + is_draft=False, + field_data=CollectionItemFieldData( + name="The Hitchhiker\'s Guide to the Galaxy", + slug="hitchhikers-guide-to-the-galaxy", + ), ), ) @@ -6656,7 +6683,7 @@ client.collections.items.create_item_live(
-
client.collections.items.delete_items_live(...) +
client.collections.items.delete_items_live(...)
@@ -6668,7 +6695,7 @@ client.collections.items.create_item_live(
-Unpublish up to 100 items from the live site and set the `isDraft` property to `true`. +Unpublish up to 100 items from the live site and set the `isDraft` property to `true`. Items will only be unpublished in the primary locale unless a `cmsLocaleId` is included in the request. @@ -6688,13 +6715,14 @@ Required scope | `CMS:write` ```python from webflow import Webflow -from webflow.resources.collections.resources.items import ( - ItemsDeleteItemsLiveRequestItemsItem, -) +from webflow.environment import WebflowEnvironment +from webflow.collections.items import ItemsDeleteItemsLiveRequestItemsItem client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.delete_items_live( collection_id="580e63fc8c9a982ac9b8b745", items=[ @@ -6726,7 +6754,7 @@ client.collections.items.delete_items_live(
-**items:** `typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem]` +**items:** `typing.List[ItemsDeleteItemsLiveRequestItemsItem]`
@@ -6746,7 +6774,7 @@ client.collections.items.delete_items_live(
-
client.collections.items.update_items_live(...) +
client.collections.items.update_items_live(...) -> CollectionItemListNoPagination
@@ -6777,15 +6805,14 @@ Required scope | `CMS:write`
```python -from webflow import ( - CollectionItemWithIdInput, - CollectionItemWithIdInputFieldData, - Webflow, -) +from webflow import Webflow, CollectionItemWithIdInput, CollectionItemWithIdInputFieldData +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.update_items_live( collection_id="580e63fc8c9a982ac9b8b745", skip_invalid_files=True, @@ -6821,7 +6848,7 @@ client.collections.items.update_items_live( name="Hasta Luego y Gracias por Todo el Pescado", slug="hasta-luego-y-gracias", ), - ), + ) ], ) @@ -6855,7 +6882,7 @@ client.collections.items.update_items_live(
-**items:** `typing.Optional[typing.Sequence[CollectionItemWithIdInput]]` +**items:** `typing.Optional[typing.List[CollectionItemWithIdInput]]`
@@ -6875,7 +6902,7 @@ client.collections.items.update_items_live(
-
client.collections.items.create_items(...) +
client.collections.items.create_items(...) -> BulkCollectionItem
@@ -6910,18 +6937,21 @@ Required scope | `CMS:write` ```python from webflow import Webflow -from webflow.resources.collections.resources.items import SingleCmsItem +from webflow.environment import WebflowEnvironment +from webflow.collections.items import SingleCmsItem client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.create_items( collection_id="580e63fc8c9a982ac9b8b745", skip_invalid_files=True, cms_locale_ids=[ "66f6e966c9e1dc700a857ca3", "66f6e966c9e1dc700a857ca4", - "66f6e966c9e1dc700a857ca5", + "66f6e966c9e1dc700a857ca5" ], is_archived=False, is_draft=False, @@ -6969,7 +6999,7 @@ client.collections.items.create_items(
-**cms_locale_ids:** `typing.Optional[typing.Sequence[str]]` — Array of identifiers for the locales where the item will be created +**cms_locale_ids:** `typing.Optional[typing.List[str]]` — Array of identifiers for the locales where the item will be created
@@ -7005,7 +7035,7 @@ client.collections.items.create_items(
-
client.collections.items.get_item(...) +
client.collections.items.get_item(...) -> CollectionItem
@@ -7035,10 +7065,13 @@ Required scope | `CMS:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.get_item( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", @@ -7095,7 +7128,7 @@ client.collections.items.get_item(
-
client.collections.items.delete_item(...) +
client.collections.items.delete_item(...)
@@ -7107,7 +7140,7 @@ client.collections.items.get_item(
-Delete an item from a collection. +Delete an item from a collection. Required scope | `CMS:write`
@@ -7125,10 +7158,13 @@ Required scope | `CMS:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.delete_item( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", @@ -7185,7 +7221,7 @@ client.collections.items.delete_item(
-
client.collections.items.update_item(...) +
client.collections.items.update_item(...) -> CollectionItem
@@ -7214,11 +7250,14 @@ Required scope | `CMS:write`
```python -from webflow import CollectionItemPatchSingleFieldData, Webflow +from webflow import Webflow, CollectionItemPatchSingleFieldData +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.update_item( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", @@ -7226,7 +7265,7 @@ client.collections.items.update_item( is_archived=False, is_draft=False, field_data=CollectionItemPatchSingleFieldData( - name="The Hitchhiker's Guide to the Galaxy", + name="The Hitchhiker\'s Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy", ), ) @@ -7261,15 +7300,7 @@ client.collections.items.update_item(
-**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. - -
-
- -
-
- -**id:** `typing.Optional[str]` — Unique identifier for the Item +**request:** `CollectionItemPatchSingle`
@@ -7277,55 +7308,7 @@ client.collections.items.update_item(
-**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item - -
-
- -
-
- -**last_published:** `typing.Optional[str]` — The date the item was last published - -
-
- -
-
- -**last_updated:** `typing.Optional[str]` — The date the item was last updated - -
-
- -
-
- -**created_on:** `typing.Optional[str]` — The date the item was created - -
-
- -
-
- -**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived - -
-
- -
-
- -**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft - -
-
- -
-
- -**field_data:** `typing.Optional[CollectionItemPatchSingleFieldData]` +**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid.
@@ -7345,7 +7328,7 @@ client.collections.items.update_item(
-
client.collections.items.get_item_live(...) +
client.collections.items.get_item_live(...) -> CollectionItem
@@ -7379,10 +7362,13 @@ Required scope | `CMS:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.get_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", @@ -7439,7 +7425,7 @@ client.collections.items.get_item_live(
-
client.collections.items.delete_item_live(...) +
client.collections.items.delete_item_live(...)
@@ -7451,7 +7437,7 @@ client.collections.items.get_item_live(
-Unpublish a live item from the site and set the `isDraft` property to `true`. +Unpublish a live item from the site and set the `isDraft` property to `true`. For bulk unpublishing, please use [this endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) @@ -7471,10 +7457,13 @@ Required scope | `CMS:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.delete_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", @@ -7531,7 +7520,7 @@ client.collections.items.delete_item_live(
-
client.collections.items.update_item_live(...) +
client.collections.items.update_item_live(...) -> CollectionItem
@@ -7560,11 +7549,14 @@ Required scope | `CMS:write`
```python -from webflow import CollectionItemPatchSingleFieldData, Webflow +from webflow import Webflow, CollectionItemPatchSingleFieldData +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.update_item_live( collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", @@ -7572,7 +7564,7 @@ client.collections.items.update_item_live( is_archived=False, is_draft=False, field_data=CollectionItemPatchSingleFieldData( - name="The Hitchhiker's Guide to the Galaxy", + name="The Hitchhiker\'s Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy", ), ) @@ -7607,15 +7599,7 @@ client.collections.items.update_item_live(
-**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. - -
-
- -
-
- -**id:** `typing.Optional[str]` — Unique identifier for the Item +**request:** `CollectionItemPatchSingle`
@@ -7623,55 +7607,7 @@ client.collections.items.update_item_live(
-**cms_locale_id:** `typing.Optional[str]` — Identifier for the locale of the CMS item - -
-
- -
-
- -**last_published:** `typing.Optional[str]` — The date the item was last published - -
-
- -
-
- -**last_updated:** `typing.Optional[str]` — The date the item was last updated - -
-
- -
-
- -**created_on:** `typing.Optional[str]` — The date the item was created - -
-
- -
-
- -**is_archived:** `typing.Optional[bool]` — Boolean determining if the Item is set to archived - -
-
- -
-
- -**is_draft:** `typing.Optional[bool]` — Boolean determining if the Item is set to draft - -
-
- -
-
- -**field_data:** `typing.Optional[CollectionItemPatchSingleFieldData]` +**skip_invalid_files:** `typing.Optional[bool]` — When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid.
@@ -7691,7 +7627,7 @@ client.collections.items.update_item_live(
-
client.collections.items.publish_item(...) +
client.collections.items.publish_item(...) -> ItemsPublishItemResponse
@@ -7721,26 +7657,21 @@ Required scope | `cms:write` ```python from webflow import Webflow -from webflow.resources.collections.resources.items import ( - ItemIDsWithLocales, - ItemsPublishItemRequestItemsItemsItem, -) +from webflow.environment import WebflowEnvironment +from webflow.collections.items import ItemIDs client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.collections.items.publish_item( collection_id="580e63fc8c9a982ac9b8b745", - request=ItemIDsWithLocales( - items=[ - ItemsPublishItemRequestItemsItemsItem( - id="643fd856d66b6528195ee2ca", - cms_locale_ids=[ - "653ad57de882f528b32e810e", - "6514390aea353fc691d69827", - "65143930ea353fc691d69cd8", - ], - ) + request=ItemIDs( + item_ids=[ + "643fd856d66b6528195ee2ca", + "643fd856d66b6528195ee2cb", + "643fd856d66b6528195ee2cc" ], ), ) @@ -7788,7 +7719,7 @@ client.collections.items.publish_item(
## Pages Scripts -
client.pages.scripts.get_custom_code(...) +
client.pages.scripts.get_custom_code(...) -> ScriptApplyList
@@ -7800,7 +7731,7 @@ client.collections.items.publish_item(
-Get all scripts applied to a page. +Get all scripts applied to a page. Required scope | `custom_code:read`
@@ -7818,10 +7749,13 @@ Required scope | `custom_code:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.pages.scripts.get_custom_code( page_id="63c720f9347c2139b248e552", ) @@ -7860,7 +7794,7 @@ client.pages.scripts.get_custom_code(
-
client.pages.scripts.upsert_custom_code(...) +
client.pages.scripts.upsert_custom_code(...) -> ScriptApplyList
@@ -7893,11 +7827,14 @@ Required scope | `custom_code:write`
```python -from webflow import ScriptApply, Webflow +from webflow import Webflow, ScriptApply +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.pages.scripts.upsert_custom_code( page_id="63c720f9347c2139b248e552", scripts=[ @@ -7905,13 +7842,15 @@ client.pages.scripts.upsert_custom_code( id="cms_slider", location="header", version="1.0.0", - attributes={"my-attribute": "some-value"}, + attributes={ + "my-attribute": "some-value" + }, ), ScriptApply( id="alert", location="header", version="0.0.1", - ), + ) ], ) @@ -7937,23 +7876,7 @@ client.pages.scripts.upsert_custom_code(
-**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page - -
-
- -
-
- -**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated - -
-
- -
-
- -**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created +**request:** `ScriptApplyList`
@@ -7973,7 +7896,7 @@ client.pages.scripts.upsert_custom_code(
-
client.pages.scripts.delete_custom_code(...) +
client.pages.scripts.delete_custom_code(...)
@@ -8007,10 +7930,13 @@ Required scope | `custom_code:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.pages.scripts.delete_custom_code( page_id="63c720f9347c2139b248e552", ) @@ -8050,7 +7976,7 @@ client.pages.scripts.delete_custom_code(
## Sites Redirects -
client.sites.redirects.list(...) +
client.sites.redirects.list(...) -> Redirects
@@ -8084,10 +8010,13 @@ Required scope: `sites:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.redirects.list( site_id="580e63e98c9a982ac9b8b741", ) @@ -8126,7 +8055,7 @@ client.sites.redirects.list(
-
client.sites.redirects.create(...) +
client.sites.redirects.create(...) -> Redirect
@@ -8160,10 +8089,13 @@ Required scope: `sites:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.redirects.create( site_id="580e63e98c9a982ac9b8b741", id="42e1a2b7aa1a13f768a0042a", @@ -8193,23 +8125,7 @@ client.sites.redirects.create(
-**id:** `typing.Optional[str]` — The ID of the specific redirect rule - -
-
- -
-
- -**from_url:** `typing.Optional[str]` — The source URL path that will be redirected. - -
-
- -
-
- -**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected. +**request:** `Redirect`
@@ -8229,7 +8145,7 @@ client.sites.redirects.create(
-
client.sites.redirects.delete(...) +
client.sites.redirects.delete(...) -> Redirects
@@ -8263,10 +8179,13 @@ Required scope: `sites:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.redirects.delete( site_id="580e63e98c9a982ac9b8b741", redirect_id="66c4cb9a20cac35ed19500e6", @@ -8294,7 +8213,7 @@ client.sites.redirects.delete(
-**redirect_id:** `str` — Unique identifier site rediect +**redirect_id:** `str` — Unique identifier site redirect
@@ -8314,7 +8233,7 @@ client.sites.redirects.delete(
-
client.sites.redirects.update(...) +
client.sites.redirects.update(...) -> Redirect
@@ -8346,10 +8265,13 @@ Required scope: `sites:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.redirects.update( site_id="580e63e98c9a982ac9b8b741", redirect_id="66c4cb9a20cac35ed19500e6", @@ -8380,7 +8302,7 @@ client.sites.redirects.update(
-**redirect_id:** `str` — Unique identifier site rediect +**redirect_id:** `str` — Unique identifier site redirect
@@ -8388,23 +8310,7 @@ client.sites.redirects.update(
-**id:** `typing.Optional[str]` — The ID of the specific redirect rule - -
-
- -
-
- -**from_url:** `typing.Optional[str]` — The source URL path that will be redirected. - -
-
- -
-
- -**to_url:** `typing.Optional[str]` — The target URL path where the user or client will be redirected. +**request:** `Redirect`
@@ -8425,7 +8331,7 @@ client.sites.redirects.update(
## Sites Plans -
client.sites.plans.get_site_plan(...) +
client.sites.plans.get_site_plan(...) -> SitePlan
@@ -8457,10 +8363,13 @@ Required scope | `sites:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.plans.get_site_plan( site_id="580e63e98c9a982ac9b8b741", ) @@ -8500,7 +8409,7 @@ client.sites.plans.get_site_plan(
## Sites RobotsTxt -
client.sites.robots_txt.get(...) +
client.sites.robots_txt.get(...) -> Robots
@@ -8532,10 +8441,13 @@ Required scope: `site_config:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.robots_txt.get( site_id="580e63e98c9a982ac9b8b741", ) @@ -8574,7 +8486,7 @@ client.sites.robots_txt.get(
-
client.sites.robots_txt.put(...) +
client.sites.robots_txt.put(...) -> Robots
@@ -8605,18 +8517,26 @@ Required scope | `site_config:write`
```python -from webflow import RobotsRulesItem, Webflow +from webflow import Webflow, RobotsRulesItem +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.robots_txt.put( site_id="580e63e98c9a982ac9b8b741", rules=[ RobotsRulesItem( user_agent="googlebot", - allows=["/public"], - disallows=["/vogon-poetry", "/total-perspective-vortex"], + allows=[ + "/public" + ], + disallows=[ + "/vogon-poetry", + "/total-perspective-vortex" + ], ) ], sitemap="https://heartofgold.ship/sitemap.xml", @@ -8644,15 +8564,7 @@ client.sites.robots_txt.put(
-**rules:** `typing.Optional[typing.Sequence[RobotsRulesItem]]` — List of rules for user agents. - -
-
- -
-
- -**sitemap:** `typing.Optional[str]` — URL to the sitemap. +**request:** `Robots`
@@ -8672,7 +8584,7 @@ client.sites.robots_txt.put(
-
client.sites.robots_txt.delete(...) +
client.sites.robots_txt.delete(...) -> Robots
@@ -8705,18 +8617,25 @@ Required scope: `site_config:write`
```python -from webflow import RobotsRulesItem, Webflow +from webflow import Webflow, RobotsRulesItem +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.robots_txt.delete( site_id="580e63e98c9a982ac9b8b741", rules=[ RobotsRulesItem( user_agent="*", - allows=["/public"], - disallows=["/bubbles"], + allows=[ + "/public" + ], + disallows=[ + "/bubbles" + ], ) ], ) @@ -8743,15 +8662,7 @@ client.sites.robots_txt.delete(
-**rules:** `typing.Optional[typing.Sequence[RobotsRulesItem]]` — List of rules for user agents. - -
-
- -
-
- -**sitemap:** `typing.Optional[str]` — URL to the sitemap. +**request:** `Robots`
@@ -8771,7 +8682,7 @@ client.sites.robots_txt.delete(
-
client.sites.robots_txt.patch(...) +
client.sites.robots_txt.patch(...) -> Robots
@@ -8802,18 +8713,26 @@ Required scope | `site_config:write`
```python -from webflow import RobotsRulesItem, Webflow +from webflow import Webflow, RobotsRulesItem +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.robots_txt.patch( site_id="580e63e98c9a982ac9b8b741", rules=[ RobotsRulesItem( user_agent="googlebot", - allows=["/public"], - disallows=["/vogon-poetry", "/total-perspective-vortex"], + allows=[ + "/public" + ], + disallows=[ + "/vogon-poetry", + "/total-perspective-vortex" + ], ) ], sitemap="https://heartofgold.ship/sitemap.xml", @@ -8841,15 +8760,7 @@ client.sites.robots_txt.patch(
-**rules:** `typing.Optional[typing.Sequence[RobotsRulesItem]]` — List of rules for user agents. - -
-
- -
-
- -**sitemap:** `typing.Optional[str]` — URL to the sitemap. +**request:** `Robots`
@@ -8870,7 +8781,7 @@ client.sites.robots_txt.patch(
## Sites WellKnown -
client.sites.well_known.put(...) +
client.sites.well_known.put(...)
@@ -8887,8 +8798,8 @@ Upload a supported well-known file to a site. The current restrictions on well-known files are as follows: - Each file must be smaller than 100kb - Less than 30 total files - - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` - + - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` + `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. @@ -8911,14 +8822,17 @@ Required scope: `site_config:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.well_known.put( site_id="580e63e98c9a982ac9b8b741", file_name="apple-app-site-association.txt", - file_data='{\n "applinks": {\n "apps": [],\n "details": [\n {\n "appID": "ABCDE12345.com.example.app",\n "paths": [ "/*", "/some/path/*" ]\n }\n ]\n }\n}\n', + file_data="{\n \"applinks\": {\n \"apps\": [],\n \"details\": [\n {\n \"appID\": \"ABCDE12345.com.example.app\",\n \"paths\": [ \"/*\", \"/some/path/*\" ]\n }\n ]\n }\n}\n", content_type="application/json", ) @@ -8980,7 +8894,7 @@ client.sites.well_known.put(
-
client.sites.well_known.delete(...) +
client.sites.well_known.delete(...)
@@ -9012,10 +8926,13 @@ Required scope: `site_config:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.well_known.delete( site_id="580e63e98c9a982ac9b8b741", ) @@ -9042,7 +8959,7 @@ client.sites.well_known.delete(
-**file_names:** `typing.Optional[typing.Sequence[str]]` — A list of file names to delete +**file_names:** `typing.Optional[typing.List[str]]` — A list of file names to delete
@@ -9063,7 +8980,7 @@ client.sites.well_known.delete(
## Sites ActivityLogs -
client.sites.activity_logs.list(...) +
client.sites.activity_logs.list(...) -> SiteActivityLogResponse
@@ -9075,7 +8992,7 @@ client.sites.well_known.delete(
-Retrieve Activity Logs for a specific Site. +Retrieve Activity Logs for a specific Site. This endpoint requires an Enterprise workspace. @@ -9095,10 +9012,13 @@ Required scope: `site_activity:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.activity_logs.list( site_id="580e63e98c9a982ac9b8b741", limit=1, @@ -9156,7 +9076,7 @@ client.sites.activity_logs.list(
## Sites Comments -
client.sites.comments.list_comment_threads(...) +
client.sites.comments.list_comment_threads(...) -> CommentThreadList
@@ -9190,10 +9110,13 @@ Required scope | `comments:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.comments.list_comment_threads( site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0", @@ -9281,7 +9204,7 @@ Unique identifier for a specific Locale.
-
client.sites.comments.get_comment_thread(...) +
client.sites.comments.get_comment_thread(...) -> CommentThread
@@ -9315,10 +9238,13 @@ Required scope | `comments:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.comments.get_comment_thread( site_id="580e63e98c9a982ac9b8b741", comment_thread_id="580e63e98c9a982ac9b8b741", @@ -9415,7 +9341,7 @@ Unique identifier for a specific Locale.
-
client.sites.comments.list_comment_replies(...) +
client.sites.comments.list_comment_replies(...) -> CommentReplyList
@@ -9449,10 +9375,13 @@ Required scope | `comments:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.comments.list_comment_replies( site_id="580e63e98c9a982ac9b8b741", comment_thread_id="580e63e98c9a982ac9b8b741", @@ -9550,7 +9479,7 @@ Unique identifier for a specific Locale.
## Sites Scripts -
client.sites.scripts.get_custom_code(...) +
client.sites.scripts.get_custom_code(...) -> ScriptApplyList
@@ -9562,11 +9491,11 @@ Unique identifier for a specific Locale.
-Get all scripts applied to a site by the App. +Get all scripts applied to a site by the App. To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. - + Required scope | `custom_code:read`
@@ -9584,10 +9513,13 @@ Required scope | `custom_code:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.scripts.get_custom_code( site_id="580e63e98c9a982ac9b8b741", ) @@ -9626,7 +9558,7 @@ client.sites.scripts.get_custom_code(
-
client.sites.scripts.upsert_custom_code(...) +
client.sites.scripts.upsert_custom_code(...) -> ScriptApplyList
@@ -9659,11 +9591,14 @@ Required scope | `custom_code:write`
```python -from webflow import ScriptApply, Webflow +from webflow import Webflow, ScriptApply +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.scripts.upsert_custom_code( site_id="580e63e98c9a982ac9b8b741", scripts=[ @@ -9671,13 +9606,15 @@ client.sites.scripts.upsert_custom_code( id="cms_slider", location="header", version="1.0.0", - attributes={"my-attribute": "some-value"}, + attributes={ + "my-attribute": "some-value" + }, ), ScriptApply( id="alert", location="header", version="0.0.1", - ), + ) ], ) @@ -9703,23 +9640,7 @@ client.sites.scripts.upsert_custom_code(
-**scripts:** `typing.Optional[typing.Sequence[ScriptApply]]` — A list of scripts applied to a Site or a Page - -
-
- -
-
- -**last_updated:** `typing.Optional[str]` — Date when the Site's scripts were last updated - -
-
- -
-
- -**created_on:** `typing.Optional[str]` — Date when the Site's scripts were created +**request:** `ScriptApplyList`
@@ -9739,7 +9660,7 @@ client.sites.scripts.upsert_custom_code(
-
client.sites.scripts.delete_custom_code(...) +
client.sites.scripts.delete_custom_code(...)
@@ -9773,10 +9694,13 @@ Required scope | `custom_code:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.scripts.delete_custom_code( site_id="580e63e98c9a982ac9b8b741", ) @@ -9815,7 +9739,7 @@ client.sites.scripts.delete_custom_code(
-
client.sites.scripts.list_custom_code_blocks(...) +
client.sites.scripts.list_custom_code_blocks(...) -> ListCustomCodeBlocks
@@ -9827,11 +9751,11 @@ client.sites.scripts.delete_custom_code(
-Get a list of scripts that have been applied to a site and/or individual pages. +Get a list of scripts that have been applied to a site and/or individual pages. - To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. - + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. + See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. @@ -9851,10 +9775,13 @@ Required scope | `custom_code:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.scripts.list_custom_code_blocks( site_id="580e63e98c9a982ac9b8b741", offset=1, @@ -9912,7 +9839,7 @@ client.sites.scripts.list_custom_code_blocks(
## Sites Forms -
client.sites.forms.list_submissions_by_site(...) +
client.sites.forms.list_submissions_by_site(...) -> FormSubmissionList
@@ -9926,7 +9853,7 @@ client.sites.scripts.list_custom_code_blocks( List all form submissions for a given site with the ability to filter submissions by a centralized `elementId`. -Add `elementId` when you want to filter form submissions to a specific form in a site. You can get the `elementId` from the [List forms endpoint](/data/reference/forms/forms/list) (displayed as `formElementId` in the response). +Add `elementId` when you want to filter form submissions to a specific form in a site. You can get the `elementId` from the [List forms endpoint](/data/reference/forms/forms/list) (displayed as `formElementId` in the response). When a form is used in a Webflow component definition, each instance of the component will yield a unique form. Adding the `elementId` in this request ensures this API response includes all submissions from that core form, wherever that form is used in instantiated components. @@ -9950,10 +9877,13 @@ Required scope | `forms:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.forms.list_submissions_by_site( site_id="580e63e98c9a982ac9b8b741", element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0", @@ -10019,7 +9949,7 @@ client.sites.forms.list_submissions_by_site(
-
client.sites.forms.list_submissions(...) +
client.sites.forms.list_submissions(...) -> FormSubmissionList
@@ -10031,7 +9961,7 @@ client.sites.forms.list_submissions_by_site(
-List form submissions for a given form ID within a specific site. +List form submissions for a given form ID within a specific site. Use the [List Form Submissions by Site endpoint](/data/reference/forms/form-submissions/list-submissions-by-site) to list form submissions for a given site with the ability to filter by a `formElementId`. @@ -10051,10 +9981,13 @@ Required scope | `forms:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.forms.list_submissions( site_id="580e63e98c9a982ac9b8b741", form_id="580e63e98c9a982ac9b8b741", @@ -10120,7 +10053,7 @@ client.sites.forms.list_submissions(
-
client.sites.forms.get_submission(...) +
client.sites.forms.get_submission(...) -> FormSubmission
@@ -10150,10 +10083,13 @@ Required scope | `forms:read` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.forms.get_submission( site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741", @@ -10201,7 +10137,7 @@ client.sites.forms.get_submission(
-
client.sites.forms.delete_submission(...) +
client.sites.forms.delete_submission(...)
@@ -10231,10 +10167,13 @@ Required scope | `forms:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.forms.delete_submission( site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741", @@ -10282,7 +10221,7 @@ client.sites.forms.delete_submission(
-
client.sites.forms.update_submission(...) +
client.sites.forms.update_submission(...) -> FormSubmission
@@ -10312,10 +10251,13 @@ Required scope | `forms:write` ```python from webflow import Webflow +from webflow.environment import WebflowEnvironment client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.sites.forms.update_submission( site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741", @@ -10351,7 +10293,7 @@ client.sites.forms.update_submission(
-**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set +**form_submission_data:** `typing.Optional[typing.Dict[str, typing.Any]]` — An existing **hidden field** defined on the form schema, and the corresponding value to set
@@ -10372,7 +10314,7 @@ client.sites.forms.update_submission(
## Workspaces AuditLogs -
client.workspaces.audit_logs.get_workspace_audit_logs(...) +
client.workspaces.audit_logs.get_workspace_audit_logs(...) -> WorkspaceAuditLogResponse
@@ -10403,25 +10345,23 @@ Required scope | `workspace_activity:read`
```python -import datetime - from webflow import Webflow +from webflow.environment import WebflowEnvironment +import datetime client = Webflow( - access_token="YOUR_ACCESS_TOKEN", + access_token="", + environment=WebflowEnvironment.DATA_API, ) + client.workspaces.audit_logs.get_workspace_audit_logs( workspace_id_or_slug="hitchhikers-workspace", limit=1, offset=1, sort_order="asc", event_type="user_access", - from_=datetime.datetime.fromisoformat( - "2025-06-22 16:00:31+00:00", - ), - to=datetime.datetime.fromisoformat( - "2025-07-22 16:00:31+00:00", - ), + from_=datetime.datetime.fromisoformat("2025-06-22T16:00:31+00:00"), + to=datetime.datetime.fromisoformat("2025-07-22T16:00:31+00:00"), ) ``` @@ -10478,7 +10418,7 @@ client.workspaces.audit_logs.get_workspace_audit_logs(
-**from_:** `typing.Optional[dt.datetime]` — The start date to filter by +**from:** `typing.Optional[datetime.datetime]` — The start date to filter by
@@ -10486,7 +10426,7 @@ client.workspaces.audit_logs.get_workspace_audit_logs(
-**to:** `typing.Optional[dt.datetime]` — The end date to filter by +**to:** `typing.Optional[datetime.datetime]` — The end date to filter by
diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e80f640 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +httpx>=0.21.2 +pydantic>= 1.9.2 +pydantic-core>=2.18.2 +typing_extensions>= 4.0.0 diff --git a/src/webflow/__init__.py b/src/webflow/__init__.py index 4c00894..48d0673 100644 --- a/src/webflow/__init__.py +++ b/src/webflow/__init__.py @@ -1,318 +1,656 @@ # This file was auto-generated by Fern from our API Definition. -from .types import ( - Application, - Asset, - AssetFolder, - AssetFolderList, - AssetUpload, - AssetUploadUploadDetails, - AssetVariant, - Assets, - Authorization, - AuthorizationAuthorization, - AuthorizationAuthorizationAuthorizedTo, - AuthorizedUser, - BadRequestErrorBody, - BulkCollectionItem, - BulkCollectionItemFieldData, - Collection, - CollectionItem, - CollectionItemChanged, - CollectionItemCreated, - CollectionItemFieldData, - CollectionItemList, - CollectionItemListNoPagination, - CollectionItemListPagination, - CollectionItemPatchSingle, - CollectionItemPatchSingleFieldData, - CollectionItemPostSingle, - CollectionItemPostSingleFieldData, - CollectionItemPublished, - CollectionItemRemoved, - CollectionItemRemovedPayload, - CollectionItemRemovedPayloadFieldData, - CollectionItemUnpublished, - CollectionItemUnpublishedPayload, - CollectionItemUnpublishedPayloadFieldData, - CollectionItemWithIdInput, - CollectionItemWithIdInputFieldData, - CollectionList, - CollectionListArrayItem, - Comment, - CommentPayload, - CommentPayloadAuthor, - CommentPayloadMentionedUsersItem, - CommentReply, - CommentReplyAuthor, - CommentReplyList, - CommentReplyListPagination, - CommentReplyMentionedUsersItem, - CommentThread, - CommentThreadAuthor, - CommentThreadList, - CommentThreadListPagination, - CommentThreadMentionedUsersItem, - Component, - ComponentDom, - ComponentInstanceNodePropertyOverridesWrite, - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, - ComponentList, - ComponentNode, - ComponentProperties, - ComponentProperty, - ComponentPropertyType, - Conflict, - CustomCodeBlock, - CustomCodeBlockType, - CustomCodeHostedResponse, - CustomCodeInlineResponse, - CustomRole, - CustomRoleAuditLogItem, - CustomRoleAuditLogItemEventSubType, - Dom, - Domain, - Domains, - EcommerceSettings, - Error, - ErrorCode, - Field, - FieldCreate, - FieldType, - FieldValidations, - FieldValidationsAdditionalProperties, - FieldValidationsAdditionalPropertiesAdditionalProperties, - ForbiddenErrorBody, - Form, - FormField, - FormFieldValue, - FormFieldValueType, - FormList, - FormResponseSettings, - FormSubmission, - FormSubmissionList, - FormSubmissionTrigger, - FormSubmissionTriggerPayload, - FormSubmissionTriggerPayloadSchemaItem, - FormSubmissionTriggerPayloadSchemaItemFieldType, - ImageNode, - ImageNodeImage, - InvalidDomain, - InvalidScopes, - InventoryItem, - InventoryItemInventoryType, - ItemsListItemsLiveRequestLastPublished, - ItemsListItemsRequestLastPublished, - ListCustomCodeBlocks, - Locale, - Locales, - Metadata, - MetadataOptionsItem, - NewOrder, - NoDomains, - Node, - Node_ComponentInstance, - Node_Image, - Node_SearchButton, - Node_Select, - Node_SubmitButton, - Node_Text, - Node_TextInput, - NotEnterprisePlanSite, - NotEnterprisePlanWorkspace, - OptionField, - Order, - OrderAddress, - OrderAddressJapanType, - OrderAddressType, - OrderBillingAddress, - OrderBillingAddressJapanType, - OrderBillingAddressType, - OrderCustomerInfo, - OrderDisputeLastStatus, - OrderDownloadFilesItem, - OrderList, - OrderMetadata, - OrderPrice, - OrderPurchasedItem, - OrderPurchasedItemVariantImage, - OrderPurchasedItemVariantImageFile, - OrderPurchasedItemVariantImageFileVariantsItem, - OrderShippingAddress, - OrderShippingAddressJapanType, - OrderShippingAddressType, - OrderStatus, - OrderTotals, - OrderTotalsExtrasItem, - OrderTotalsExtrasItemType, - Page, - PageCreatedWebhook, - PageCreatedWebhookPayload, - PageDeletedWebhook, - PageDeletedWebhookPayload, - PageList, - PageMetadataUpdatedWebhook, - PageMetadataUpdatedWebhookPayload, - PageOpenGraph, - PageSeo, - Pagination, - Payload, - PayloadFieldData, - PaypalDetails, - Product, - ProductAndSkUs, - ProductAndSkUsList, - ProductFieldData, - ProductFieldDataEcProductType, - ProductFieldDataTaxCategory, - PublishStatus, - Redirect, - Redirects, - ReferenceField, - ReferenceFieldMetadata, - ReferenceFieldType, - RegisteredScriptList, - Robots, - RobotsRulesItem, - ScriptApply, - ScriptApplyList, - ScriptApplyLocation, - Scripts, - SearchButtonNode, - SearchButtonNodeWrite, - Select, - SelectNode, - SelectNodeChoicesItem, - SelectNodeWriteChoicesItem, - SettingChange, - SettingChangeAuditLogItem, - SingleLocaleCreatedPayload, - SingleLocaleCreatedPayloadFieldData, - Site, - SiteActivityLogItem, - SiteActivityLogItemEvent, - SiteActivityLogItemResourceOperation, - SiteActivityLogItemUser, - SiteActivityLogResponse, - SiteDataCollectionType, - SiteMembership, - SiteMembershipAuditLogItem, - SiteMembershipAuditLogItemEventSubType, - SitePlan, - SitePlanId, - SitePlanName, - SitePublish, - SitePublishPayload, - Sites, - Sku, - SkuFieldData, - SkuFieldDataCompareAtPrice, - SkuFieldDataEcSkuBillingMethod, - SkuFieldDataEcSkuSubscriptionPlan, - SkuFieldDataEcSkuSubscriptionPlanInterval, - SkuFieldDataEcSkuSubscriptionPlanPlansItem, - SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus, - SkuFieldDataPrice, - SkuPropertyList, - SkuPropertyListEnumItem, - SkuValueList, - StaticField, - StaticFieldType, - StripeCard, - StripeCardBrand, - StripeCardExpires, - StripeDetails, - SubmitButtonNode, - SubmitButtonNodeWrite, - Text, - TextInputNode, - TextInputNodeWrite, - TextNode, - TextNodeText, - TextNodeWrite, - TriggerType, - UpdatedOrder, - UserAccess, - UserAccessAuditLogItem, - UserAccessAuditLogItemEventSubType, - Webhook, - WebhookFilter, - WebhookList, - WorkspaceAuditLogItem, - WorkspaceAuditLogItemActor, - WorkspaceAuditLogItemPayloadSettingChangeMethod, - WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess, - WorkspaceAuditLogItemPayloadSiteMembershipMethod, - WorkspaceAuditLogItemPayloadSiteMembershipSite, - WorkspaceAuditLogItemPayloadSiteMembershipTargetUser, - WorkspaceAuditLogItemPayloadSiteMembershipUserType, - WorkspaceAuditLogItemPayloadUserAccessMethod, - WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod, - WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, - WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem, - WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, - WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod, - WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, - WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType, - WorkspaceAuditLogItemWorkspace, - WorkspaceAuditLogItem_CustomRole, - WorkspaceAuditLogItem_SiteMembership, - WorkspaceAuditLogItem_UserAccess, - WorkspaceAuditLogItem_WorkspaceInvitation, - WorkspaceAuditLogItem_WorkspaceMembership, - WorkspaceAuditLogItem_WorkspaceSetting, - WorkspaceAuditLogResponse, - WorkspaceInvitation, - WorkspaceInvitationAuditLogItem, - WorkspaceInvitationAuditLogItemEventSubType, - WorkspaceMembership, - WorkspaceMembershipAuditLogItem, - WorkspaceMembershipAuditLogItemEventSubType, -) -from .errors import ( - BadRequestError, - ConflictError, - ForbiddenError, - InternalServerError, - NotFoundError, - TooManyRequestsError, - UnauthorizedError, -) -from .resources import ( - ComponentDomWriteNodesItem, - ComponentPropertiesWritePropertiesItem, - ComponentsUpdateContentResponse, - ComponentsUpdatePropertiesResponse, - EcommInventoryChangedPayload, - InventoryUpdateRequestInventoryType, - OrdersListRequestStatus, - OrdersRefundRequestReason, - PageDomWriteNodesItem, - PageMetadataWriteOpenGraph, - PageMetadataWriteSeo, - ProductSkuCreateProduct, - ProductSkuCreateSku, - ProductsCreateSkuResponse, - SitesPublishResponse, - UpdateStaticContentResponse, - assets, - collections, - components, - ecommerce, - forms, - inventory, - orders, - pages, - products, - scripts, - sites, - token, - webhooks, - workspaces, -) -from .client import AsyncWebflow, Webflow -from .environment import WebflowEnvironment -from .version import __version__ +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import ( + Application, + Asset, + AssetFolder, + AssetFolderList, + AssetUpload, + AssetUploadUploadDetails, + AssetVariant, + Assets, + Authorization, + AuthorizationAuthorization, + AuthorizationAuthorizationAuthorizedTo, + AuthorizedUser, + BadRequestErrorBody, + BulkCollectionItem, + BulkCollectionItemFieldData, + Collection, + CollectionItem, + CollectionItemChanged, + CollectionItemCreated, + CollectionItemFieldData, + CollectionItemList, + CollectionItemListNoPagination, + CollectionItemListPagination, + CollectionItemPatchSingle, + CollectionItemPatchSingleFieldData, + CollectionItemPostSingle, + CollectionItemPostSingleFieldData, + CollectionItemPublished, + CollectionItemRemoved, + CollectionItemRemovedPayload, + CollectionItemRemovedPayloadFieldData, + CollectionItemUnpublished, + CollectionItemUnpublishedPayload, + CollectionItemUnpublishedPayloadFieldData, + CollectionItemWithIdInput, + CollectionItemWithIdInputFieldData, + CollectionList, + CollectionListArrayItem, + Comment, + CommentPayload, + CommentPayloadAuthor, + CommentPayloadMentionedUsersItem, + CommentReply, + CommentReplyAuthor, + CommentReplyList, + CommentReplyListPagination, + CommentReplyMentionedUsersItem, + CommentThread, + CommentThreadAuthor, + CommentThreadList, + CommentThreadListPagination, + CommentThreadMentionedUsersItem, + Component, + ComponentDom, + ComponentInstanceNodePropertyOverridesWrite, + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + ComponentList, + ComponentNode, + ComponentProperties, + ComponentProperty, + ComponentPropertyType, + Conflict, + CustomCodeBlock, + CustomCodeBlockType, + CustomCodeHostedResponse, + CustomCodeInlineResponse, + CustomRole, + CustomRoleAuditLogItem, + CustomRoleAuditLogItemEventSubType, + Dom, + Domain, + Domains, + EcommerceSettings, + Error, + ErrorCode, + Field, + FieldCreate, + FieldType, + FieldValidations, + FieldValidationsAdditionalProperties, + FieldValidationsAdditionalPropertiesAdditionalProperties, + ForbiddenErrorBody, + Form, + FormField, + FormFieldValue, + FormFieldValueType, + FormList, + FormResponseSettings, + FormSubmission, + FormSubmissionList, + FormSubmissionTrigger, + FormSubmissionTriggerPayload, + FormSubmissionTriggerPayloadSchemaItem, + FormSubmissionTriggerPayloadSchemaItemFieldType, + ImageNode, + ImageNodeImage, + InvalidDomain, + InvalidScopes, + InventoryItem, + InventoryItemInventoryType, + ItemsListItemsLiveRequestLastPublished, + ItemsListItemsRequestLastPublished, + ListCustomCodeBlocks, + Locale, + Locales, + Metadata, + MetadataOptionsItem, + NewOrder, + NoDomains, + Node, + Node_ComponentInstance, + Node_Image, + Node_SearchButton, + Node_Select, + Node_SubmitButton, + Node_Text, + Node_TextInput, + NotEnterprisePlanSite, + NotEnterprisePlanWorkspace, + OptionField, + Order, + OrderAddress, + OrderAddressJapanType, + OrderAddressType, + OrderBillingAddress, + OrderBillingAddressJapanType, + OrderBillingAddressType, + OrderCustomerInfo, + OrderDisputeLastStatus, + OrderDownloadFilesItem, + OrderList, + OrderMetadata, + OrderPrice, + OrderPurchasedItem, + OrderPurchasedItemVariantImage, + OrderPurchasedItemVariantImageFile, + OrderPurchasedItemVariantImageFileVariantsItem, + OrderShippingAddress, + OrderShippingAddressJapanType, + OrderShippingAddressType, + OrderStatus, + OrderTotals, + OrderTotalsExtrasItem, + OrderTotalsExtrasItemType, + Page, + PageCreatedWebhook, + PageCreatedWebhookPayload, + PageDeletedWebhook, + PageDeletedWebhookPayload, + PageList, + PageMetadataUpdatedWebhook, + PageMetadataUpdatedWebhookPayload, + PageOpenGraph, + PageSeo, + Pagination, + Payload, + PayloadFieldData, + PaypalDetails, + Product, + ProductAndSkUs, + ProductAndSkUsList, + ProductFieldData, + ProductFieldDataEcProductType, + ProductFieldDataTaxCategory, + PublishStatus, + Redirect, + Redirects, + ReferenceField, + ReferenceFieldMetadata, + ReferenceFieldType, + RegisteredScriptList, + Robots, + RobotsRulesItem, + ScriptApply, + ScriptApplyList, + ScriptApplyLocation, + Scripts, + SearchButtonNode, + SearchButtonNodeWrite, + Select, + SelectNode, + SelectNodeChoicesItem, + SelectNodeWriteChoicesItem, + SettingChange, + SettingChangeAuditLogItem, + SingleLocaleCreatedPayload, + SingleLocaleCreatedPayloadFieldData, + Site, + SiteActivityLogItem, + SiteActivityLogItemEvent, + SiteActivityLogItemResourceOperation, + SiteActivityLogItemUser, + SiteActivityLogResponse, + SiteDataCollectionType, + SiteMembership, + SiteMembershipAuditLogItem, + SiteMembershipAuditLogItemEventSubType, + SitePlan, + SitePlanId, + SitePlanName, + SitePublish, + SitePublishPayload, + Sites, + Sku, + SkuFieldData, + SkuFieldDataCompareAtPrice, + SkuFieldDataEcSkuBillingMethod, + SkuFieldDataEcSkuSubscriptionPlan, + SkuFieldDataEcSkuSubscriptionPlanInterval, + SkuFieldDataEcSkuSubscriptionPlanPlansItem, + SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus, + SkuFieldDataPrice, + SkuPropertyList, + SkuPropertyListEnumItem, + SkuValueList, + StaticField, + StaticFieldType, + StripeCard, + StripeCardBrand, + StripeCardExpires, + StripeDetails, + SubmitButtonNode, + SubmitButtonNodeWrite, + Text, + TextInputNode, + TextInputNodeWrite, + TextNode, + TextNodeText, + TextNodeWrite, + TriggerType, + UpdatedOrder, + UserAccess, + UserAccessAuditLogItem, + UserAccessAuditLogItemEventSubType, + Webhook, + WebhookFilter, + WebhookList, + WorkspaceAuditLogItem, + WorkspaceAuditLogItemActor, + WorkspaceAuditLogItemPayloadSettingChangeMethod, + WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess, + WorkspaceAuditLogItemPayloadSiteMembershipMethod, + WorkspaceAuditLogItemPayloadSiteMembershipSite, + WorkspaceAuditLogItemPayloadSiteMembershipTargetUser, + WorkspaceAuditLogItemPayloadSiteMembershipUserType, + WorkspaceAuditLogItemPayloadUserAccessMethod, + WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod, + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem, + WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, + WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod, + WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, + WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType, + WorkspaceAuditLogItemWorkspace, + WorkspaceAuditLogItem_CustomRole, + WorkspaceAuditLogItem_SiteMembership, + WorkspaceAuditLogItem_UserAccess, + WorkspaceAuditLogItem_WorkspaceInvitation, + WorkspaceAuditLogItem_WorkspaceMembership, + WorkspaceAuditLogItem_WorkspaceSetting, + WorkspaceAuditLogResponse, + WorkspaceInvitation, + WorkspaceInvitationAuditLogItem, + WorkspaceInvitationAuditLogItemEventSubType, + WorkspaceMembership, + WorkspaceMembershipAuditLogItem, + WorkspaceMembershipAuditLogItemEventSubType, + ) + from .errors import ( + BadRequestError, + ConflictError, + ForbiddenError, + InternalServerError, + NotFoundError, + TooManyRequestsError, + UnauthorizedError, + ) + from .resources import ( + ComponentDomWriteNodesItem, + ComponentPropertiesWritePropertiesItem, + ComponentsUpdateContentResponse, + ComponentsUpdatePropertiesResponse, + EcommInventoryChangedPayload, + InventoryUpdateRequestInventoryType, + OrdersListRequestStatus, + OrdersRefundRequestReason, + PageDomWriteNodesItem, + PageMetadataWriteOpenGraph, + PageMetadataWriteSeo, + ProductSkuCreateProduct, + ProductSkuCreateSku, + ProductsCreateSkuResponse, + SitesPublishResponse, + UpdateStaticContentResponse, + assets, + collections, + components, + ecommerce, + forms, + inventory, + orders, + pages, + products, + scripts, + sites, + token, + webhooks, + workspaces, + ) + from .client import AsyncWebflow, Webflow + from .environment import WebflowEnvironment + from .version import __version__ +_dynamic_imports: typing.Dict[str, str] = { + "Application": ".types", + "Asset": ".types", + "AssetFolder": ".types", + "AssetFolderList": ".types", + "AssetUpload": ".types", + "AssetUploadUploadDetails": ".types", + "AssetVariant": ".types", + "Assets": ".types", + "AsyncWebflow": ".client", + "Authorization": ".types", + "AuthorizationAuthorization": ".types", + "AuthorizationAuthorizationAuthorizedTo": ".types", + "AuthorizedUser": ".types", + "BadRequestError": ".errors", + "BadRequestErrorBody": ".types", + "BulkCollectionItem": ".types", + "BulkCollectionItemFieldData": ".types", + "Collection": ".types", + "CollectionItem": ".types", + "CollectionItemChanged": ".types", + "CollectionItemCreated": ".types", + "CollectionItemFieldData": ".types", + "CollectionItemList": ".types", + "CollectionItemListNoPagination": ".types", + "CollectionItemListPagination": ".types", + "CollectionItemPatchSingle": ".types", + "CollectionItemPatchSingleFieldData": ".types", + "CollectionItemPostSingle": ".types", + "CollectionItemPostSingleFieldData": ".types", + "CollectionItemPublished": ".types", + "CollectionItemRemoved": ".types", + "CollectionItemRemovedPayload": ".types", + "CollectionItemRemovedPayloadFieldData": ".types", + "CollectionItemUnpublished": ".types", + "CollectionItemUnpublishedPayload": ".types", + "CollectionItemUnpublishedPayloadFieldData": ".types", + "CollectionItemWithIdInput": ".types", + "CollectionItemWithIdInputFieldData": ".types", + "CollectionList": ".types", + "CollectionListArrayItem": ".types", + "Comment": ".types", + "CommentPayload": ".types", + "CommentPayloadAuthor": ".types", + "CommentPayloadMentionedUsersItem": ".types", + "CommentReply": ".types", + "CommentReplyAuthor": ".types", + "CommentReplyList": ".types", + "CommentReplyListPagination": ".types", + "CommentReplyMentionedUsersItem": ".types", + "CommentThread": ".types", + "CommentThreadAuthor": ".types", + "CommentThreadList": ".types", + "CommentThreadListPagination": ".types", + "CommentThreadMentionedUsersItem": ".types", + "Component": ".types", + "ComponentDom": ".types", + "ComponentDomWriteNodesItem": ".resources", + "ComponentInstanceNodePropertyOverridesWrite": ".types", + "ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem": ".types", + "ComponentList": ".types", + "ComponentNode": ".types", + "ComponentProperties": ".types", + "ComponentPropertiesWritePropertiesItem": ".resources", + "ComponentProperty": ".types", + "ComponentPropertyType": ".types", + "ComponentsUpdateContentResponse": ".resources", + "ComponentsUpdatePropertiesResponse": ".resources", + "Conflict": ".types", + "ConflictError": ".errors", + "CustomCodeBlock": ".types", + "CustomCodeBlockType": ".types", + "CustomCodeHostedResponse": ".types", + "CustomCodeInlineResponse": ".types", + "CustomRole": ".types", + "CustomRoleAuditLogItem": ".types", + "CustomRoleAuditLogItemEventSubType": ".types", + "Dom": ".types", + "Domain": ".types", + "Domains": ".types", + "EcommInventoryChangedPayload": ".resources", + "EcommerceSettings": ".types", + "Error": ".types", + "ErrorCode": ".types", + "Field": ".types", + "FieldCreate": ".types", + "FieldType": ".types", + "FieldValidations": ".types", + "FieldValidationsAdditionalProperties": ".types", + "FieldValidationsAdditionalPropertiesAdditionalProperties": ".types", + "ForbiddenError": ".errors", + "ForbiddenErrorBody": ".types", + "Form": ".types", + "FormField": ".types", + "FormFieldValue": ".types", + "FormFieldValueType": ".types", + "FormList": ".types", + "FormResponseSettings": ".types", + "FormSubmission": ".types", + "FormSubmissionList": ".types", + "FormSubmissionTrigger": ".types", + "FormSubmissionTriggerPayload": ".types", + "FormSubmissionTriggerPayloadSchemaItem": ".types", + "FormSubmissionTriggerPayloadSchemaItemFieldType": ".types", + "ImageNode": ".types", + "ImageNodeImage": ".types", + "InternalServerError": ".errors", + "InvalidDomain": ".types", + "InvalidScopes": ".types", + "InventoryItem": ".types", + "InventoryItemInventoryType": ".types", + "InventoryUpdateRequestInventoryType": ".resources", + "ItemsListItemsLiveRequestLastPublished": ".types", + "ItemsListItemsRequestLastPublished": ".types", + "ListCustomCodeBlocks": ".types", + "Locale": ".types", + "Locales": ".types", + "Metadata": ".types", + "MetadataOptionsItem": ".types", + "NewOrder": ".types", + "NoDomains": ".types", + "Node": ".types", + "Node_ComponentInstance": ".types", + "Node_Image": ".types", + "Node_SearchButton": ".types", + "Node_Select": ".types", + "Node_SubmitButton": ".types", + "Node_Text": ".types", + "Node_TextInput": ".types", + "NotEnterprisePlanSite": ".types", + "NotEnterprisePlanWorkspace": ".types", + "NotFoundError": ".errors", + "OptionField": ".types", + "Order": ".types", + "OrderAddress": ".types", + "OrderAddressJapanType": ".types", + "OrderAddressType": ".types", + "OrderBillingAddress": ".types", + "OrderBillingAddressJapanType": ".types", + "OrderBillingAddressType": ".types", + "OrderCustomerInfo": ".types", + "OrderDisputeLastStatus": ".types", + "OrderDownloadFilesItem": ".types", + "OrderList": ".types", + "OrderMetadata": ".types", + "OrderPrice": ".types", + "OrderPurchasedItem": ".types", + "OrderPurchasedItemVariantImage": ".types", + "OrderPurchasedItemVariantImageFile": ".types", + "OrderPurchasedItemVariantImageFileVariantsItem": ".types", + "OrderShippingAddress": ".types", + "OrderShippingAddressJapanType": ".types", + "OrderShippingAddressType": ".types", + "OrderStatus": ".types", + "OrderTotals": ".types", + "OrderTotalsExtrasItem": ".types", + "OrderTotalsExtrasItemType": ".types", + "OrdersListRequestStatus": ".resources", + "OrdersRefundRequestReason": ".resources", + "Page": ".types", + "PageCreatedWebhook": ".types", + "PageCreatedWebhookPayload": ".types", + "PageDeletedWebhook": ".types", + "PageDeletedWebhookPayload": ".types", + "PageDomWriteNodesItem": ".resources", + "PageList": ".types", + "PageMetadataUpdatedWebhook": ".types", + "PageMetadataUpdatedWebhookPayload": ".types", + "PageMetadataWriteOpenGraph": ".resources", + "PageMetadataWriteSeo": ".resources", + "PageOpenGraph": ".types", + "PageSeo": ".types", + "Pagination": ".types", + "Payload": ".types", + "PayloadFieldData": ".types", + "PaypalDetails": ".types", + "Product": ".types", + "ProductAndSkUs": ".types", + "ProductAndSkUsList": ".types", + "ProductFieldData": ".types", + "ProductFieldDataEcProductType": ".types", + "ProductFieldDataTaxCategory": ".types", + "ProductSkuCreateProduct": ".resources", + "ProductSkuCreateSku": ".resources", + "ProductsCreateSkuResponse": ".resources", + "PublishStatus": ".types", + "Redirect": ".types", + "Redirects": ".types", + "ReferenceField": ".types", + "ReferenceFieldMetadata": ".types", + "ReferenceFieldType": ".types", + "RegisteredScriptList": ".types", + "Robots": ".types", + "RobotsRulesItem": ".types", + "ScriptApply": ".types", + "ScriptApplyList": ".types", + "ScriptApplyLocation": ".types", + "Scripts": ".types", + "SearchButtonNode": ".types", + "SearchButtonNodeWrite": ".types", + "Select": ".types", + "SelectNode": ".types", + "SelectNodeChoicesItem": ".types", + "SelectNodeWriteChoicesItem": ".types", + "SettingChange": ".types", + "SettingChangeAuditLogItem": ".types", + "SingleLocaleCreatedPayload": ".types", + "SingleLocaleCreatedPayloadFieldData": ".types", + "Site": ".types", + "SiteActivityLogItem": ".types", + "SiteActivityLogItemEvent": ".types", + "SiteActivityLogItemResourceOperation": ".types", + "SiteActivityLogItemUser": ".types", + "SiteActivityLogResponse": ".types", + "SiteDataCollectionType": ".types", + "SiteMembership": ".types", + "SiteMembershipAuditLogItem": ".types", + "SiteMembershipAuditLogItemEventSubType": ".types", + "SitePlan": ".types", + "SitePlanId": ".types", + "SitePlanName": ".types", + "SitePublish": ".types", + "SitePublishPayload": ".types", + "Sites": ".types", + "SitesPublishResponse": ".resources", + "Sku": ".types", + "SkuFieldData": ".types", + "SkuFieldDataCompareAtPrice": ".types", + "SkuFieldDataEcSkuBillingMethod": ".types", + "SkuFieldDataEcSkuSubscriptionPlan": ".types", + "SkuFieldDataEcSkuSubscriptionPlanInterval": ".types", + "SkuFieldDataEcSkuSubscriptionPlanPlansItem": ".types", + "SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus": ".types", + "SkuFieldDataPrice": ".types", + "SkuPropertyList": ".types", + "SkuPropertyListEnumItem": ".types", + "SkuValueList": ".types", + "StaticField": ".types", + "StaticFieldType": ".types", + "StripeCard": ".types", + "StripeCardBrand": ".types", + "StripeCardExpires": ".types", + "StripeDetails": ".types", + "SubmitButtonNode": ".types", + "SubmitButtonNodeWrite": ".types", + "Text": ".types", + "TextInputNode": ".types", + "TextInputNodeWrite": ".types", + "TextNode": ".types", + "TextNodeText": ".types", + "TextNodeWrite": ".types", + "TooManyRequestsError": ".errors", + "TriggerType": ".types", + "UnauthorizedError": ".errors", + "UpdateStaticContentResponse": ".resources", + "UpdatedOrder": ".types", + "UserAccess": ".types", + "UserAccessAuditLogItem": ".types", + "UserAccessAuditLogItemEventSubType": ".types", + "Webflow": ".client", + "WebflowEnvironment": ".environment", + "Webhook": ".types", + "WebhookFilter": ".types", + "WebhookList": ".types", + "WorkspaceAuditLogItem": ".types", + "WorkspaceAuditLogItemActor": ".types", + "WorkspaceAuditLogItemPayloadSettingChangeMethod": ".types", + "WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess": ".types", + "WorkspaceAuditLogItemPayloadSiteMembershipMethod": ".types", + "WorkspaceAuditLogItemPayloadSiteMembershipSite": ".types", + "WorkspaceAuditLogItemPayloadSiteMembershipTargetUser": ".types", + "WorkspaceAuditLogItemPayloadSiteMembershipUserType": ".types", + "WorkspaceAuditLogItemPayloadUserAccessMethod": ".types", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod": ".types", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser": ".types", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem": ".types", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType": ".types", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod": ".types", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser": ".types", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType": ".types", + "WorkspaceAuditLogItemWorkspace": ".types", + "WorkspaceAuditLogItem_CustomRole": ".types", + "WorkspaceAuditLogItem_SiteMembership": ".types", + "WorkspaceAuditLogItem_UserAccess": ".types", + "WorkspaceAuditLogItem_WorkspaceInvitation": ".types", + "WorkspaceAuditLogItem_WorkspaceMembership": ".types", + "WorkspaceAuditLogItem_WorkspaceSetting": ".types", + "WorkspaceAuditLogResponse": ".types", + "WorkspaceInvitation": ".types", + "WorkspaceInvitationAuditLogItem": ".types", + "WorkspaceInvitationAuditLogItemEventSubType": ".types", + "WorkspaceMembership": ".types", + "WorkspaceMembershipAuditLogItem": ".types", + "WorkspaceMembershipAuditLogItemEventSubType": ".types", + "__version__": ".version", + "assets": ".resources", + "collections": ".resources", + "components": ".resources", + "ecommerce": ".resources", + "forms": ".resources", + "inventory": ".resources", + "orders": ".resources", + "pages": ".resources", + "products": ".resources", + "scripts": ".resources", + "sites": ".resources", + "token": ".resources", + "webhooks": ".resources", + "workspaces": ".resources", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "Application", diff --git a/src/webflow/client.py b/src/webflow/client.py index 6f76267..bc75156 100644 --- a/src/webflow/client.py +++ b/src/webflow/client.py @@ -1,38 +1,29 @@ # This file was auto-generated by Fern from our API Definition. -from .environment import WebflowEnvironment +from __future__ import annotations + import typing + import httpx -from .core.client_wrapper import SyncClientWrapper -from .resources.token.client import TokenClient -from .resources.sites.client import SitesClient -from .resources.collections.client import CollectionsClient -from .resources.pages.client import PagesClient -from .resources.components.client import ComponentsClient -from .resources.scripts.client import ScriptsClient -from .resources.assets.client import AssetsClient -from .resources.webhooks.client import WebhooksClient -from .resources.forms.client import FormsClient -from .resources.products.client import ProductsClient -from .resources.orders.client import OrdersClient -from .resources.inventory.client import InventoryClient -from .resources.ecommerce.client import EcommerceClient -from .resources.workspaces.client import WorkspacesClient -from .core.client_wrapper import AsyncClientWrapper -from .resources.token.client import AsyncTokenClient -from .resources.sites.client import AsyncSitesClient -from .resources.collections.client import AsyncCollectionsClient -from .resources.pages.client import AsyncPagesClient -from .resources.components.client import AsyncComponentsClient -from .resources.scripts.client import AsyncScriptsClient -from .resources.assets.client import AsyncAssetsClient -from .resources.webhooks.client import AsyncWebhooksClient -from .resources.forms.client import AsyncFormsClient -from .resources.products.client import AsyncProductsClient -from .resources.orders.client import AsyncOrdersClient -from .resources.inventory.client import AsyncInventoryClient -from .resources.ecommerce.client import AsyncEcommerceClient -from .resources.workspaces.client import AsyncWorkspacesClient +from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .core.logging import LogConfig, Logger +from .environment import WebflowEnvironment + +if typing.TYPE_CHECKING: + from .resources.assets.client import AssetsClient, AsyncAssetsClient + from .resources.collections.client import AsyncCollectionsClient, CollectionsClient + from .resources.components.client import AsyncComponentsClient, ComponentsClient + from .resources.ecommerce.client import AsyncEcommerceClient, EcommerceClient + from .resources.forms.client import AsyncFormsClient, FormsClient + from .resources.inventory.client import AsyncInventoryClient, InventoryClient + from .resources.orders.client import AsyncOrdersClient, OrdersClient + from .resources.pages.client import AsyncPagesClient, PagesClient + from .resources.products.client import AsyncProductsClient, ProductsClient + from .resources.scripts.client import AsyncScriptsClient, ScriptsClient + from .resources.sites.client import AsyncSitesClient, SitesClient + from .resources.token.client import AsyncTokenClient, TokenClient + from .resources.webhooks.client import AsyncWebhooksClient, WebhooksClient + from .resources.workspaces.client import AsyncWorkspacesClient, WorkspacesClient class Webflow: @@ -50,7 +41,10 @@ class Webflow: - access_token : typing.Optional[typing.Union[str, typing.Callable[[], str]]] + access_token : typing.Union[str, typing.Callable[[], str]] + headers : typing.Optional[typing.Dict[str, str]] + Additional headers to send with every request. + timeout : typing.Optional[float] The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced. @@ -60,6 +54,9 @@ class Webflow: httpx_client : typing.Optional[httpx.Client] The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. + logging : typing.Optional[typing.Union[LogConfig, Logger]] + Configure logging for the SDK. Accepts a LogConfig dict with 'level' (debug/info/warn/error), 'logger' (custom logger implementation), and 'silent' (boolean, defaults to True) fields. You can also pass a pre-configured Logger instance. + Examples -------- from webflow import Webflow @@ -73,36 +70,154 @@ def __init__( self, *, environment: WebflowEnvironment = WebflowEnvironment.DATA_API, - access_token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + access_token: typing.Union[str, typing.Callable[[], str]], + headers: typing.Optional[typing.Dict[str, str]] = None, timeout: typing.Optional[float] = None, follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.Client] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): - _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None + _defaulted_timeout = ( + timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read + ) self._client_wrapper = SyncClientWrapper( environment=environment, access_token=access_token, + headers=headers, httpx_client=httpx_client if httpx_client is not None else httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects) if follow_redirects is not None else httpx.Client(timeout=_defaulted_timeout), timeout=_defaulted_timeout, + logging=logging, ) - self.token = TokenClient(client_wrapper=self._client_wrapper) - self.sites = SitesClient(client_wrapper=self._client_wrapper) - self.collections = CollectionsClient(client_wrapper=self._client_wrapper) - self.pages = PagesClient(client_wrapper=self._client_wrapper) - self.components = ComponentsClient(client_wrapper=self._client_wrapper) - self.scripts = ScriptsClient(client_wrapper=self._client_wrapper) - self.assets = AssetsClient(client_wrapper=self._client_wrapper) - self.webhooks = WebhooksClient(client_wrapper=self._client_wrapper) - self.forms = FormsClient(client_wrapper=self._client_wrapper) - self.products = ProductsClient(client_wrapper=self._client_wrapper) - self.orders = OrdersClient(client_wrapper=self._client_wrapper) - self.inventory = InventoryClient(client_wrapper=self._client_wrapper) - self.ecommerce = EcommerceClient(client_wrapper=self._client_wrapper) - self.workspaces = WorkspacesClient(client_wrapper=self._client_wrapper) + self._token: typing.Optional[TokenClient] = None + self._sites: typing.Optional[SitesClient] = None + self._collections: typing.Optional[CollectionsClient] = None + self._pages: typing.Optional[PagesClient] = None + self._components: typing.Optional[ComponentsClient] = None + self._scripts: typing.Optional[ScriptsClient] = None + self._assets: typing.Optional[AssetsClient] = None + self._webhooks: typing.Optional[WebhooksClient] = None + self._forms: typing.Optional[FormsClient] = None + self._products: typing.Optional[ProductsClient] = None + self._orders: typing.Optional[OrdersClient] = None + self._inventory: typing.Optional[InventoryClient] = None + self._ecommerce: typing.Optional[EcommerceClient] = None + self._workspaces: typing.Optional[WorkspacesClient] = None + + @property + def token(self): + if self._token is None: + from .resources.token.client import TokenClient # noqa: E402 + + self._token = TokenClient(client_wrapper=self._client_wrapper) + return self._token + + @property + def sites(self): + if self._sites is None: + from .resources.sites.client import SitesClient # noqa: E402 + + self._sites = SitesClient(client_wrapper=self._client_wrapper) + return self._sites + + @property + def collections(self): + if self._collections is None: + from .resources.collections.client import CollectionsClient # noqa: E402 + + self._collections = CollectionsClient(client_wrapper=self._client_wrapper) + return self._collections + + @property + def pages(self): + if self._pages is None: + from .resources.pages.client import PagesClient # noqa: E402 + + self._pages = PagesClient(client_wrapper=self._client_wrapper) + return self._pages + + @property + def components(self): + if self._components is None: + from .resources.components.client import ComponentsClient # noqa: E402 + + self._components = ComponentsClient(client_wrapper=self._client_wrapper) + return self._components + + @property + def scripts(self): + if self._scripts is None: + from .resources.scripts.client import ScriptsClient # noqa: E402 + + self._scripts = ScriptsClient(client_wrapper=self._client_wrapper) + return self._scripts + + @property + def assets(self): + if self._assets is None: + from .resources.assets.client import AssetsClient # noqa: E402 + + self._assets = AssetsClient(client_wrapper=self._client_wrapper) + return self._assets + + @property + def webhooks(self): + if self._webhooks is None: + from .resources.webhooks.client import WebhooksClient # noqa: E402 + + self._webhooks = WebhooksClient(client_wrapper=self._client_wrapper) + return self._webhooks + + @property + def forms(self): + if self._forms is None: + from .resources.forms.client import FormsClient # noqa: E402 + + self._forms = FormsClient(client_wrapper=self._client_wrapper) + return self._forms + + @property + def products(self): + if self._products is None: + from .resources.products.client import ProductsClient # noqa: E402 + + self._products = ProductsClient(client_wrapper=self._client_wrapper) + return self._products + + @property + def orders(self): + if self._orders is None: + from .resources.orders.client import OrdersClient # noqa: E402 + + self._orders = OrdersClient(client_wrapper=self._client_wrapper) + return self._orders + + @property + def inventory(self): + if self._inventory is None: + from .resources.inventory.client import InventoryClient # noqa: E402 + + self._inventory = InventoryClient(client_wrapper=self._client_wrapper) + return self._inventory + + @property + def ecommerce(self): + if self._ecommerce is None: + from .resources.ecommerce.client import EcommerceClient # noqa: E402 + + self._ecommerce = EcommerceClient(client_wrapper=self._client_wrapper) + return self._ecommerce + + @property + def workspaces(self): + if self._workspaces is None: + from .resources.workspaces.client import WorkspacesClient # noqa: E402 + + self._workspaces = WorkspacesClient(client_wrapper=self._client_wrapper) + return self._workspaces class AsyncWebflow: @@ -120,7 +235,10 @@ class AsyncWebflow: - access_token : typing.Optional[typing.Union[str, typing.Callable[[], str]]] + access_token : typing.Union[str, typing.Callable[[], str]] + headers : typing.Optional[typing.Dict[str, str]] + Additional headers to send with every request. + timeout : typing.Optional[float] The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced. @@ -130,6 +248,9 @@ class AsyncWebflow: httpx_client : typing.Optional[httpx.AsyncClient] The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. + logging : typing.Optional[typing.Union[LogConfig, Logger]] + Configure logging for the SDK. Accepts a LogConfig dict with 'level' (debug/info/warn/error), 'logger' (custom logger implementation), and 'silent' (boolean, defaults to True) fields. You can also pass a pre-configured Logger instance. + Examples -------- from webflow import AsyncWebflow @@ -143,33 +264,151 @@ def __init__( self, *, environment: WebflowEnvironment = WebflowEnvironment.DATA_API, - access_token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + access_token: typing.Union[str, typing.Callable[[], str]], + headers: typing.Optional[typing.Dict[str, str]] = None, timeout: typing.Optional[float] = None, follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.AsyncClient] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): - _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None + _defaulted_timeout = ( + timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read + ) self._client_wrapper = AsyncClientWrapper( environment=environment, access_token=access_token, + headers=headers, httpx_client=httpx_client if httpx_client is not None else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects) if follow_redirects is not None else httpx.AsyncClient(timeout=_defaulted_timeout), timeout=_defaulted_timeout, + logging=logging, ) - self.token = AsyncTokenClient(client_wrapper=self._client_wrapper) - self.sites = AsyncSitesClient(client_wrapper=self._client_wrapper) - self.collections = AsyncCollectionsClient(client_wrapper=self._client_wrapper) - self.pages = AsyncPagesClient(client_wrapper=self._client_wrapper) - self.components = AsyncComponentsClient(client_wrapper=self._client_wrapper) - self.scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) - self.assets = AsyncAssetsClient(client_wrapper=self._client_wrapper) - self.webhooks = AsyncWebhooksClient(client_wrapper=self._client_wrapper) - self.forms = AsyncFormsClient(client_wrapper=self._client_wrapper) - self.products = AsyncProductsClient(client_wrapper=self._client_wrapper) - self.orders = AsyncOrdersClient(client_wrapper=self._client_wrapper) - self.inventory = AsyncInventoryClient(client_wrapper=self._client_wrapper) - self.ecommerce = AsyncEcommerceClient(client_wrapper=self._client_wrapper) - self.workspaces = AsyncWorkspacesClient(client_wrapper=self._client_wrapper) + self._token: typing.Optional[AsyncTokenClient] = None + self._sites: typing.Optional[AsyncSitesClient] = None + self._collections: typing.Optional[AsyncCollectionsClient] = None + self._pages: typing.Optional[AsyncPagesClient] = None + self._components: typing.Optional[AsyncComponentsClient] = None + self._scripts: typing.Optional[AsyncScriptsClient] = None + self._assets: typing.Optional[AsyncAssetsClient] = None + self._webhooks: typing.Optional[AsyncWebhooksClient] = None + self._forms: typing.Optional[AsyncFormsClient] = None + self._products: typing.Optional[AsyncProductsClient] = None + self._orders: typing.Optional[AsyncOrdersClient] = None + self._inventory: typing.Optional[AsyncInventoryClient] = None + self._ecommerce: typing.Optional[AsyncEcommerceClient] = None + self._workspaces: typing.Optional[AsyncWorkspacesClient] = None + + @property + def token(self): + if self._token is None: + from .resources.token.client import AsyncTokenClient # noqa: E402 + + self._token = AsyncTokenClient(client_wrapper=self._client_wrapper) + return self._token + + @property + def sites(self): + if self._sites is None: + from .resources.sites.client import AsyncSitesClient # noqa: E402 + + self._sites = AsyncSitesClient(client_wrapper=self._client_wrapper) + return self._sites + + @property + def collections(self): + if self._collections is None: + from .resources.collections.client import AsyncCollectionsClient # noqa: E402 + + self._collections = AsyncCollectionsClient(client_wrapper=self._client_wrapper) + return self._collections + + @property + def pages(self): + if self._pages is None: + from .resources.pages.client import AsyncPagesClient # noqa: E402 + + self._pages = AsyncPagesClient(client_wrapper=self._client_wrapper) + return self._pages + + @property + def components(self): + if self._components is None: + from .resources.components.client import AsyncComponentsClient # noqa: E402 + + self._components = AsyncComponentsClient(client_wrapper=self._client_wrapper) + return self._components + + @property + def scripts(self): + if self._scripts is None: + from .resources.scripts.client import AsyncScriptsClient # noqa: E402 + + self._scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) + return self._scripts + + @property + def assets(self): + if self._assets is None: + from .resources.assets.client import AsyncAssetsClient # noqa: E402 + + self._assets = AsyncAssetsClient(client_wrapper=self._client_wrapper) + return self._assets + + @property + def webhooks(self): + if self._webhooks is None: + from .resources.webhooks.client import AsyncWebhooksClient # noqa: E402 + + self._webhooks = AsyncWebhooksClient(client_wrapper=self._client_wrapper) + return self._webhooks + + @property + def forms(self): + if self._forms is None: + from .resources.forms.client import AsyncFormsClient # noqa: E402 + + self._forms = AsyncFormsClient(client_wrapper=self._client_wrapper) + return self._forms + + @property + def products(self): + if self._products is None: + from .resources.products.client import AsyncProductsClient # noqa: E402 + + self._products = AsyncProductsClient(client_wrapper=self._client_wrapper) + return self._products + + @property + def orders(self): + if self._orders is None: + from .resources.orders.client import AsyncOrdersClient # noqa: E402 + + self._orders = AsyncOrdersClient(client_wrapper=self._client_wrapper) + return self._orders + + @property + def inventory(self): + if self._inventory is None: + from .resources.inventory.client import AsyncInventoryClient # noqa: E402 + + self._inventory = AsyncInventoryClient(client_wrapper=self._client_wrapper) + return self._inventory + + @property + def ecommerce(self): + if self._ecommerce is None: + from .resources.ecommerce.client import AsyncEcommerceClient # noqa: E402 + + self._ecommerce = AsyncEcommerceClient(client_wrapper=self._client_wrapper) + return self._ecommerce + + @property + def workspaces(self): + if self._workspaces is None: + from .resources.workspaces.client import AsyncWorkspacesClient # noqa: E402 + + self._workspaces = AsyncWorkspacesClient(client_wrapper=self._client_wrapper) + return self._workspaces diff --git a/src/webflow/core/__init__.py b/src/webflow/core/__init__.py index f03aecb..4fb6e12 100644 --- a/src/webflow/core/__init__.py +++ b/src/webflow/core/__init__.py @@ -1,43 +1,121 @@ # This file was auto-generated by Fern from our API Definition. -from .api_error import ApiError -from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper -from .datetime_utils import serialize_datetime -from .file import File, convert_file_dict_to_httpx_tuples, with_content_type -from .http_client import AsyncHttpClient, HttpClient -from .jsonable_encoder import jsonable_encoder -from .pydantic_utilities import ( - IS_PYDANTIC_V2, - UniversalBaseModel, - UniversalRootModel, - parse_obj_as, - universal_field_validator, - universal_root_validator, - update_forward_refs, -) -from .query_encoder import encode_query -from .remove_none_from_dict import remove_none_from_dict -from .request_options import RequestOptions -from .serialization import FieldMetadata, convert_and_respect_annotation_metadata +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .api_error import ApiError + from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper + from .datetime_utils import Rfc2822DateTime, parse_rfc2822_datetime, serialize_datetime + from .file import File, convert_file_dict_to_httpx_tuples, with_content_type + from .http_client import AsyncHttpClient, HttpClient + from .http_response import AsyncHttpResponse, HttpResponse + from .jsonable_encoder import jsonable_encoder + from .logging import ConsoleLogger, ILogger, LogConfig, LogLevel, Logger, create_logger + from .parse_error import ParsingError + from .pydantic_utilities import ( + IS_PYDANTIC_V2, + UniversalBaseModel, + UniversalRootModel, + parse_obj_as, + universal_field_validator, + universal_root_validator, + update_forward_refs, + ) + from .query_encoder import encode_query + from .remove_none_from_dict import remove_none_from_dict + from .request_options import RequestOptions + from .serialization import FieldMetadata, convert_and_respect_annotation_metadata +_dynamic_imports: typing.Dict[str, str] = { + "ApiError": ".api_error", + "AsyncClientWrapper": ".client_wrapper", + "AsyncHttpClient": ".http_client", + "AsyncHttpResponse": ".http_response", + "BaseClientWrapper": ".client_wrapper", + "ConsoleLogger": ".logging", + "FieldMetadata": ".serialization", + "File": ".file", + "HttpClient": ".http_client", + "HttpResponse": ".http_response", + "ILogger": ".logging", + "IS_PYDANTIC_V2": ".pydantic_utilities", + "LogConfig": ".logging", + "LogLevel": ".logging", + "Logger": ".logging", + "ParsingError": ".parse_error", + "RequestOptions": ".request_options", + "Rfc2822DateTime": ".datetime_utils", + "SyncClientWrapper": ".client_wrapper", + "UniversalBaseModel": ".pydantic_utilities", + "UniversalRootModel": ".pydantic_utilities", + "convert_and_respect_annotation_metadata": ".serialization", + "convert_file_dict_to_httpx_tuples": ".file", + "create_logger": ".logging", + "encode_query": ".query_encoder", + "jsonable_encoder": ".jsonable_encoder", + "parse_obj_as": ".pydantic_utilities", + "parse_rfc2822_datetime": ".datetime_utils", + "remove_none_from_dict": ".remove_none_from_dict", + "serialize_datetime": ".datetime_utils", + "universal_field_validator": ".pydantic_utilities", + "universal_root_validator": ".pydantic_utilities", + "update_forward_refs": ".pydantic_utilities", + "with_content_type": ".file", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "ApiError", "AsyncClientWrapper", "AsyncHttpClient", + "AsyncHttpResponse", "BaseClientWrapper", + "ConsoleLogger", "FieldMetadata", "File", "HttpClient", + "HttpResponse", + "ILogger", "IS_PYDANTIC_V2", + "LogConfig", + "LogLevel", + "Logger", + "ParsingError", "RequestOptions", + "Rfc2822DateTime", "SyncClientWrapper", "UniversalBaseModel", "UniversalRootModel", "convert_and_respect_annotation_metadata", "convert_file_dict_to_httpx_tuples", + "create_logger", "encode_query", "jsonable_encoder", "parse_obj_as", + "parse_rfc2822_datetime", "remove_none_from_dict", "serialize_datetime", "universal_field_validator", diff --git a/src/webflow/core/api_error.py b/src/webflow/core/api_error.py index 2e9fc54..6f850a6 100644 --- a/src/webflow/core/api_error.py +++ b/src/webflow/core/api_error.py @@ -1,15 +1,23 @@ # This file was auto-generated by Fern from our API Definition. -import typing +from typing import Any, Dict, Optional class ApiError(Exception): - status_code: typing.Optional[int] - body: typing.Any + headers: Optional[Dict[str, str]] + status_code: Optional[int] + body: Any - def __init__(self, *, status_code: typing.Optional[int] = None, body: typing.Any = None): + def __init__( + self, + *, + headers: Optional[Dict[str, str]] = None, + status_code: Optional[int] = None, + body: Any = None, + ) -> None: + self.headers = headers self.status_code = status_code self.body = body def __str__(self) -> str: - return f"status_code: {self.status_code}, body: {self.body}" + return f"headers: {self.headers}, status_code: {self.status_code}, body: {self.body}" diff --git a/src/webflow/core/client_wrapper.py b/src/webflow/core/client_wrapper.py index 3849c42..39a2e70 100644 --- a/src/webflow/core/client_wrapper.py +++ b/src/webflow/core/client_wrapper.py @@ -1,41 +1,53 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ..environment import WebflowEnvironment + import httpx -from .http_client import HttpClient -from .http_client import AsyncHttpClient +from ..environment import WebflowEnvironment +from .http_client import AsyncHttpClient, HttpClient +from .logging import LogConfig, Logger class BaseClientWrapper: def __init__( self, *, - access_token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + access_token: typing.Union[str, typing.Callable[[], str]], + headers: typing.Optional[typing.Dict[str, str]] = None, environment: WebflowEnvironment, timeout: typing.Optional[float] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): self._access_token = access_token + self._headers = headers self._environment = environment self._timeout = timeout + self._logging = logging def get_headers(self) -> typing.Dict[str, str]: + import platform + headers: typing.Dict[str, str] = { + "User-Agent": "webflow/1.2.1", "X-Fern-Language": "Python", + "X-Fern-Runtime": f"python/{platform.python_version()}", + "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}", "X-Fern-SDK-Name": "webflow", "X-Fern-SDK-Version": "1.2.1", + **(self.get_custom_headers() or {}), } - access_token = self._get_access_token() - if access_token is not None: - headers["Authorization"] = f"Bearer {access_token}" + headers["Authorization"] = f"Bearer {self._get_access_token()}" return headers - def _get_access_token(self) -> typing.Optional[str]: - if isinstance(self._access_token, str) or self._access_token is None: + def _get_access_token(self) -> str: + if isinstance(self._access_token, str): return self._access_token else: return self._access_token() + def get_custom_headers(self) -> typing.Optional[typing.Dict[str, str]]: + return self._headers + def get_environment(self) -> WebflowEnvironment: return self._environment @@ -47,14 +59,21 @@ class SyncClientWrapper(BaseClientWrapper): def __init__( self, *, - access_token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + access_token: typing.Union[str, typing.Callable[[], str]], + headers: typing.Optional[typing.Dict[str, str]] = None, environment: WebflowEnvironment, timeout: typing.Optional[float] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, httpx_client: httpx.Client, ): - super().__init__(access_token=access_token, environment=environment, timeout=timeout) + super().__init__( + access_token=access_token, headers=headers, environment=environment, timeout=timeout, logging=logging + ) self.httpx_client = HttpClient( - httpx_client=httpx_client, base_headers=self.get_headers, base_timeout=self.get_timeout + httpx_client=httpx_client, + base_headers=self.get_headers, + base_timeout=self.get_timeout, + logging_config=self._logging, ) @@ -62,12 +81,29 @@ class AsyncClientWrapper(BaseClientWrapper): def __init__( self, *, - access_token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + access_token: typing.Union[str, typing.Callable[[], str]], + headers: typing.Optional[typing.Dict[str, str]] = None, environment: WebflowEnvironment, timeout: typing.Optional[float] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, + async_token: typing.Optional[typing.Callable[[], typing.Awaitable[str]]] = None, httpx_client: httpx.AsyncClient, ): - super().__init__(access_token=access_token, environment=environment, timeout=timeout) + super().__init__( + access_token=access_token, headers=headers, environment=environment, timeout=timeout, logging=logging + ) + self._async_token = async_token self.httpx_client = AsyncHttpClient( - httpx_client=httpx_client, base_headers=self.get_headers, base_timeout=self.get_timeout + httpx_client=httpx_client, + base_headers=self.get_headers, + base_timeout=self.get_timeout, + async_base_headers=self.async_get_headers, + logging_config=self._logging, ) + + async def async_get_headers(self) -> typing.Dict[str, str]: + headers = self.get_headers() + if self._async_token is not None: + token = await self._async_token() + headers["Authorization"] = f"Bearer {token}" + return headers diff --git a/src/webflow/core/datetime_utils.py b/src/webflow/core/datetime_utils.py index 7c9864a..a12b2ad 100644 --- a/src/webflow/core/datetime_utils.py +++ b/src/webflow/core/datetime_utils.py @@ -1,6 +1,48 @@ # This file was auto-generated by Fern from our API Definition. import datetime as dt +from email.utils import parsedate_to_datetime +from typing import Any + +import pydantic + +IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.") + + +def parse_rfc2822_datetime(v: Any) -> dt.datetime: + """ + Parse an RFC 2822 datetime string (e.g., "Wed, 02 Oct 2002 13:00:00 GMT") + into a datetime object. If the value is already a datetime, return it as-is. + Falls back to ISO 8601 parsing if RFC 2822 parsing fails. + """ + if isinstance(v, dt.datetime): + return v + if isinstance(v, str): + try: + return parsedate_to_datetime(v) + except Exception: + pass + # Fallback to ISO 8601 parsing + return dt.datetime.fromisoformat(v.replace("Z", "+00:00")) + raise ValueError(f"Expected str or datetime, got {type(v)}") + + +class Rfc2822DateTime(dt.datetime): + """A datetime subclass that parses RFC 2822 date strings. + + On Pydantic V1, uses __get_validators__ for pre-validation. + On Pydantic V2, uses __get_pydantic_core_schema__ for BeforeValidator-style parsing. + """ + + @classmethod + def __get_validators__(cls): # type: ignore[no-untyped-def] + yield parse_rfc2822_datetime + + @classmethod + def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> Any: # type: ignore[override] + from pydantic_core import core_schema + + return core_schema.no_info_before_validator_function(parse_rfc2822_datetime, core_schema.datetime_schema()) def serialize_datetime(v: dt.datetime) -> str: diff --git a/src/webflow/core/force_multipart.py b/src/webflow/core/force_multipart.py new file mode 100644 index 0000000..5440913 --- /dev/null +++ b/src/webflow/core/force_multipart.py @@ -0,0 +1,18 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict + + +class ForceMultipartDict(Dict[str, Any]): + """ + A dictionary subclass that always evaluates to True in boolean contexts. + + This is used to force multipart/form-data encoding in HTTP requests even when + the dictionary is empty, which would normally evaluate to False. + """ + + def __bool__(self) -> bool: + return True + + +FORCE_MULTIPART = ForceMultipartDict() diff --git a/src/webflow/core/http_client.py b/src/webflow/core/http_client.py index 1a1a131..ee93758 100644 --- a/src/webflow/core/http_client.py +++ b/src/webflow/core/http_client.py @@ -2,25 +2,25 @@ import asyncio import email.utils -import json import re import time import typing -import urllib.parse from contextlib import asynccontextmanager, contextmanager from random import random import httpx - from .file import File, convert_file_dict_to_httpx_tuples +from .force_multipart import FORCE_MULTIPART from .jsonable_encoder import jsonable_encoder +from .logging import LogConfig, Logger, create_logger from .query_encoder import encode_query -from .remove_none_from_dict import remove_none_from_dict +from .remove_none_from_dict import remove_none_from_dict as remove_none_from_dict from .request_options import RequestOptions +from httpx._types import RequestFiles -INITIAL_RETRY_DELAY_SECONDS = 0.5 -MAX_RETRY_DELAY_SECONDS = 10 -MAX_RETRY_DELAY_SECONDS_FROM_HEADER = 30 +INITIAL_RETRY_DELAY_SECONDS = 1.0 +MAX_RETRY_DELAY_SECONDS = 60.0 +JITTER_FACTOR = 0.2 # 20% random jitter def _parse_retry_after(response_headers: httpx.Headers) -> typing.Optional[float]: @@ -64,6 +64,38 @@ def _parse_retry_after(response_headers: httpx.Headers) -> typing.Optional[float return seconds +def _add_positive_jitter(delay: float) -> float: + """Add positive jitter (0-20%) to prevent thundering herd.""" + jitter_multiplier = 1 + random() * JITTER_FACTOR + return delay * jitter_multiplier + + +def _add_symmetric_jitter(delay: float) -> float: + """Add symmetric jitter (±10%) for exponential backoff.""" + jitter_multiplier = 1 + (random() - 0.5) * JITTER_FACTOR + return delay * jitter_multiplier + + +def _parse_x_ratelimit_reset(response_headers: httpx.Headers) -> typing.Optional[float]: + """ + Parse the X-RateLimit-Reset header (Unix timestamp in seconds). + Returns seconds to wait, or None if header is missing/invalid. + """ + reset_time_str = response_headers.get("x-ratelimit-reset") + if reset_time_str is None: + return None + + try: + reset_time = int(reset_time_str) + delay = reset_time - time.time() + if delay > 0: + return delay + except (ValueError, TypeError): + pass + + return None + + def _retry_timeout(response: httpx.Response, retries: int) -> float: """ Determine the amount of time to wait before retrying a request. @@ -71,22 +103,89 @@ def _retry_timeout(response: httpx.Response, retries: int) -> float: with a jitter to determine the number of seconds to wait. """ - # If the API asks us to wait a certain amount of time (and it's a reasonable amount), just do what it says. + # 1. Check Retry-After header first retry_after = _parse_retry_after(response.headers) - if retry_after is not None and retry_after <= MAX_RETRY_DELAY_SECONDS_FROM_HEADER: - return retry_after + if retry_after is not None and retry_after > 0: + return min(retry_after, MAX_RETRY_DELAY_SECONDS) - # Apply exponential backoff, capped at MAX_RETRY_DELAY_SECONDS. - retry_delay = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS) + # 2. Check X-RateLimit-Reset header (with positive jitter) + ratelimit_reset = _parse_x_ratelimit_reset(response.headers) + if ratelimit_reset is not None: + return _add_positive_jitter(min(ratelimit_reset, MAX_RETRY_DELAY_SECONDS)) - # Add a randomness / jitter to the retry delay to avoid overwhelming the server with retries. - timeout = retry_delay * (1 - 0.25 * random()) - return timeout if timeout >= 0 else 0 + # 3. Fall back to exponential backoff (with symmetric jitter) + backoff = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS) + return _add_symmetric_jitter(backoff) def _should_retry(response: httpx.Response) -> bool: - retriable_400s = [429, 408, 409] - return response.status_code >= 500 or response.status_code in retriable_400s + retryable_400s = [429, 408, 409] + return response.status_code >= 500 or response.status_code in retryable_400s + + +_SENSITIVE_HEADERS = frozenset( + { + "authorization", + "www-authenticate", + "x-api-key", + "api-key", + "apikey", + "x-api-token", + "x-auth-token", + "auth-token", + "cookie", + "set-cookie", + "proxy-authorization", + "proxy-authenticate", + "x-csrf-token", + "x-xsrf-token", + "x-session-token", + "x-access-token", + } +) + + +def _redact_headers(headers: typing.Dict[str, str]) -> typing.Dict[str, str]: + return {k: ("[REDACTED]" if k.lower() in _SENSITIVE_HEADERS else v) for k, v in headers.items()} + + +def _build_url(base_url: str, path: typing.Optional[str]) -> str: + """ + Build a full URL by joining a base URL with a path. + + This function correctly handles base URLs that contain path prefixes (e.g., tenant-based URLs) + by using string concatenation instead of urllib.parse.urljoin(), which would incorrectly + strip path components when the path starts with '/'. + + Example: + >>> _build_url("https://cloud.example.com/org/tenant/api", "/users") + 'https://cloud.example.com/org/tenant/api/users' + + Args: + base_url: The base URL, which may contain path prefixes. + path: The path to append. Can be None or empty string. + + Returns: + The full URL with base_url and path properly joined. + """ + if not path: + return base_url + return f"{base_url.rstrip('/')}/{path.lstrip('/')}" + + +def _maybe_filter_none_from_multipart_data( + data: typing.Optional[typing.Any], + request_files: typing.Optional[RequestFiles], + force_multipart: typing.Optional[bool], +) -> typing.Optional[typing.Any]: + """ + Filter None values from data body for multipart/form requests. + This prevents httpx from converting None to empty strings in multipart encoding. + Only applies when files are present or force_multipart is True. + """ + if data is not None and isinstance(data, typing.Mapping) and (request_files or force_multipart): + return remove_none_from_dict(data) + return data def remove_omit_from_dict( @@ -143,8 +242,19 @@ def get_request_body( # If both data and json are None, we send json data in the event extra properties are specified json_body = maybe_filter_request_body(json, request_options, omit) - # If you have an empty JSON body, you should just send None - return (json_body if json_body != {} else None), data_body if data_body != {} else None + has_additional_body_parameters = bool( + request_options is not None and request_options.get("additional_body_parameters") + ) + + # Only collapse empty dict to None when the body was not explicitly provided + # and there are no additional body parameters. This preserves explicit empty + # bodies (e.g., when an endpoint has a request body type but all fields are optional). + if json_body == {} and json is None and not has_additional_body_parameters: + json_body = None + if data_body == {} and data is None and not has_additional_body_parameters: + data_body = None + + return json_body, data_body class HttpClient: @@ -155,11 +265,13 @@ def __init__( base_timeout: typing.Callable[[], typing.Optional[float]], base_headers: typing.Callable[[], typing.Dict[str, str]], base_url: typing.Optional[typing.Callable[[], str]] = None, + logging_config: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): self.base_url = base_url self.base_timeout = base_timeout self.base_headers = base_headers self.httpx_client = httpx_client + self.logger = create_logger(logging_config) def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str: base_url = maybe_base_url @@ -180,11 +292,17 @@ def request( json: typing.Optional[typing.Any] = None, data: typing.Optional[typing.Any] = None, content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, - files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, headers: typing.Optional[typing.Dict[str, typing.Any]] = None, request_options: typing.Optional[RequestOptions] = None, retries: int = 0, omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, ) -> httpx.Response: base_url = self.get_base_url(base_url) timeout = ( @@ -195,49 +313,72 @@ def request( json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) - response = self.httpx_client.request( - method=method, - url=urllib.parse.urljoin(f"{base_url}/", path), - headers=jsonable_encoder( + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + + data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart) + + # Compute encoded params separately to avoid passing empty list to httpx + # (httpx strips existing query params from URL when params=[] is passed) + _encoded_params = encode_query( + jsonable_encoder( remove_none_from_dict( - { - **self.base_headers(), - **(headers if headers is not None else {}), - **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), - } - ) - ), - params=encode_query( - jsonable_encoder( - remove_none_from_dict( - remove_omit_from_dict( - { - **(params if params is not None else {}), - **( - request_options.get("additional_query_parameters", {}) or {} - if request_options is not None - else {} - ), - }, - omit, - ) + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) or {} + if request_options is not None + else {} + ), + }, + omit, ) ) - ), + ) + ) + + _request_url = _build_url(base_url, path) + _request_headers = jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), + } + ) + ) + + if self.logger.is_debug(): + self.logger.debug( + "Making HTTP request", + method=method, + url=_request_url, + headers=_redact_headers(_request_headers), + has_body=json_body is not None or data_body is not None, + ) + + response = self.httpx_client.request( + method=method, + url=_request_url, + headers=_request_headers, + params=_encoded_params if _encoded_params else None, json=json_body, data=data_body, content=content, - files=( - convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) - if (files is not None and files is not omit) - else None - ), + files=request_files, timeout=timeout, ) - max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0 + max_retries: int = request_options.get("max_retries", 2) if request_options is not None else 2 if _should_retry(response=response): - if max_retries > retries: + if retries < max_retries: time.sleep(_retry_timeout(response=response, retries=retries)) return self.request( path=path, @@ -253,6 +394,24 @@ def request( omit=omit, ) + if self.logger.is_debug(): + if 200 <= response.status_code < 400: + self.logger.debug( + "HTTP request succeeded", + method=method, + url=_request_url, + status_code=response.status_code, + ) + + if self.logger.is_error(): + if response.status_code >= 400: + self.logger.error( + "HTTP request failed with error status", + method=method, + url=_request_url, + status_code=response.status_code, + ) + return response @contextmanager @@ -266,11 +425,17 @@ def stream( json: typing.Optional[typing.Any] = None, data: typing.Optional[typing.Any] = None, content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, - files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, headers: typing.Optional[typing.Dict[str, typing.Any]] = None, request_options: typing.Optional[RequestOptions] = None, retries: int = 0, omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, ) -> typing.Iterator[httpx.Response]: base_url = self.get_base_url(base_url) timeout = ( @@ -279,45 +444,67 @@ def stream( else self.base_timeout() ) + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) - with self.httpx_client.stream( - method=method, - url=urllib.parse.urljoin(f"{base_url}/", path), - headers=jsonable_encoder( + data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart) + + # Compute encoded params separately to avoid passing empty list to httpx + # (httpx strips existing query params from URL when params=[] is passed) + _encoded_params = encode_query( + jsonable_encoder( remove_none_from_dict( - { - **self.base_headers(), - **(headers if headers is not None else {}), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - params=encode_query( - jsonable_encoder( - remove_none_from_dict( - remove_omit_from_dict( - { - **(params if params is not None else {}), - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - }, - omit, - ) + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) + if request_options is not None + else {} + ), + }, + omit, ) ) - ), + ) + ) + + _request_url = _build_url(base_url, path) + _request_headers = jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ) + + if self.logger.is_debug(): + self.logger.debug( + "Making streaming HTTP request", + method=method, + url=_request_url, + headers=_redact_headers(_request_headers), + ) + + with self.httpx_client.stream( + method=method, + url=_request_url, + headers=_request_headers, + params=_encoded_params if _encoded_params else None, json=json_body, data=data_body, content=content, - files=( - convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) - if (files is not None and files is not omit) - else None - ), + files=request_files, timeout=timeout, ) as stream: yield stream @@ -331,11 +518,20 @@ def __init__( base_timeout: typing.Callable[[], typing.Optional[float]], base_headers: typing.Callable[[], typing.Dict[str, str]], base_url: typing.Optional[typing.Callable[[], str]] = None, + async_base_headers: typing.Optional[typing.Callable[[], typing.Awaitable[typing.Dict[str, str]]]] = None, + logging_config: typing.Optional[typing.Union[LogConfig, Logger]] = None, ): self.base_url = base_url self.base_timeout = base_timeout self.base_headers = base_headers + self.async_base_headers = async_base_headers self.httpx_client = httpx_client + self.logger = create_logger(logging_config) + + async def _get_headers(self) -> typing.Dict[str, str]: + if self.async_base_headers is not None: + return await self.async_base_headers() + return self.base_headers() def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str: base_url = maybe_base_url @@ -356,11 +552,17 @@ async def request( json: typing.Optional[typing.Any] = None, data: typing.Optional[typing.Any] = None, content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, - files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, headers: typing.Optional[typing.Dict[str, typing.Any]] = None, request_options: typing.Optional[RequestOptions] = None, retries: int = 0, omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, ) -> httpx.Response: base_url = self.get_base_url(base_url) timeout = ( @@ -369,52 +571,77 @@ async def request( else self.base_timeout() ) + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) - # Add the input to each of these and do None-safety checks - response = await self.httpx_client.request( - method=method, - url=urllib.parse.urljoin(f"{base_url}/", path), - headers=jsonable_encoder( + data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart) + + # Get headers (supports async token providers) + _headers = await self._get_headers() + + # Compute encoded params separately to avoid passing empty list to httpx + # (httpx strips existing query params from URL when params=[] is passed) + _encoded_params = encode_query( + jsonable_encoder( remove_none_from_dict( - { - **self.base_headers(), - **(headers if headers is not None else {}), - **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), - } - ) - ), - params=encode_query( - jsonable_encoder( - remove_none_from_dict( - remove_omit_from_dict( - { - **(params if params is not None else {}), - **( - request_options.get("additional_query_parameters", {}) or {} - if request_options is not None - else {} - ), - }, - omit, - ) + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) or {} + if request_options is not None + else {} + ), + }, + omit, ) ) - ), + ) + ) + + _request_url = _build_url(base_url, path) + _request_headers = jsonable_encoder( + remove_none_from_dict( + { + **_headers, + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), + } + ) + ) + + if self.logger.is_debug(): + self.logger.debug( + "Making HTTP request", + method=method, + url=_request_url, + headers=_redact_headers(_request_headers), + has_body=json_body is not None or data_body is not None, + ) + + response = await self.httpx_client.request( + method=method, + url=_request_url, + headers=_request_headers, + params=_encoded_params if _encoded_params else None, json=json_body, data=data_body, content=content, - files=( - convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) - if files is not None - else None - ), + files=request_files, timeout=timeout, ) - max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0 + max_retries: int = request_options.get("max_retries", 2) if request_options is not None else 2 if _should_retry(response=response): - if max_retries > retries: + if retries < max_retries: await asyncio.sleep(_retry_timeout(response=response, retries=retries)) return await self.request( path=path, @@ -429,6 +656,25 @@ async def request( retries=retries + 1, omit=omit, ) + + if self.logger.is_debug(): + if 200 <= response.status_code < 400: + self.logger.debug( + "HTTP request succeeded", + method=method, + url=_request_url, + status_code=response.status_code, + ) + + if self.logger.is_error(): + if response.status_code >= 400: + self.logger.error( + "HTTP request failed with error status", + method=method, + url=_request_url, + status_code=response.status_code, + ) + return response @asynccontextmanager @@ -442,11 +688,17 @@ async def stream( json: typing.Optional[typing.Any] = None, data: typing.Optional[typing.Any] = None, content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, - files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, headers: typing.Optional[typing.Dict[str, typing.Any]] = None, request_options: typing.Optional[RequestOptions] = None, retries: int = 0, omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, ) -> typing.AsyncIterator[httpx.Response]: base_url = self.get_base_url(base_url) timeout = ( @@ -455,45 +707,70 @@ async def stream( else self.base_timeout() ) + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) - async with self.httpx_client.stream( - method=method, - url=urllib.parse.urljoin(f"{base_url}/", path), - headers=jsonable_encoder( + data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart) + + # Get headers (supports async token providers) + _headers = await self._get_headers() + + # Compute encoded params separately to avoid passing empty list to httpx + # (httpx strips existing query params from URL when params=[] is passed) + _encoded_params = encode_query( + jsonable_encoder( remove_none_from_dict( - { - **self.base_headers(), - **(headers if headers is not None else {}), - **(request_options.get("additional_headers", {}) if request_options is not None else {}), - } - ) - ), - params=encode_query( - jsonable_encoder( - remove_none_from_dict( - remove_omit_from_dict( - { - **(params if params is not None else {}), - **( - request_options.get("additional_query_parameters", {}) - if request_options is not None - else {} - ), - }, - omit=omit, - ) + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) + if request_options is not None + else {} + ), + }, + omit=omit, ) ) - ), + ) + ) + + _request_url = _build_url(base_url, path) + _request_headers = jsonable_encoder( + remove_none_from_dict( + { + **_headers, + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ) + + if self.logger.is_debug(): + self.logger.debug( + "Making streaming HTTP request", + method=method, + url=_request_url, + headers=_redact_headers(_request_headers), + ) + + async with self.httpx_client.stream( + method=method, + url=_request_url, + headers=_request_headers, + params=_encoded_params if _encoded_params else None, json=json_body, data=data_body, content=content, - files=( - convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) - if files is not None - else None - ), + files=request_files, timeout=timeout, ) as stream: yield stream diff --git a/src/webflow/core/http_response.py b/src/webflow/core/http_response.py new file mode 100644 index 0000000..00bb109 --- /dev/null +++ b/src/webflow/core/http_response.py @@ -0,0 +1,59 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Dict, Generic, TypeVar + +import httpx + +# Generic to represent the underlying type of the data wrapped by the HTTP response. +T = TypeVar("T") + + +class BaseHttpResponse: + """Minimalist HTTP response wrapper that exposes response headers and status code.""" + + _response: httpx.Response + + def __init__(self, response: httpx.Response): + self._response = response + + @property + def headers(self) -> Dict[str, str]: + return dict(self._response.headers) + + @property + def status_code(self) -> int: + return self._response.status_code + + +class HttpResponse(Generic[T], BaseHttpResponse): + """HTTP response wrapper that exposes response headers and data.""" + + _data: T + + def __init__(self, response: httpx.Response, data: T): + super().__init__(response) + self._data = data + + @property + def data(self) -> T: + return self._data + + def close(self) -> None: + self._response.close() + + +class AsyncHttpResponse(Generic[T], BaseHttpResponse): + """HTTP response wrapper that exposes response headers and data.""" + + _data: T + + def __init__(self, response: httpx.Response, data: T): + super().__init__(response) + self._data = data + + @property + def data(self) -> T: + return self._data + + async def close(self) -> None: + await self._response.aclose() diff --git a/src/webflow/core/http_sse/__init__.py b/src/webflow/core/http_sse/__init__.py new file mode 100644 index 0000000..730e5a3 --- /dev/null +++ b/src/webflow/core/http_sse/__init__.py @@ -0,0 +1,42 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from ._api import EventSource, aconnect_sse, connect_sse + from ._exceptions import SSEError + from ._models import ServerSentEvent +_dynamic_imports: typing.Dict[str, str] = { + "EventSource": "._api", + "SSEError": "._exceptions", + "ServerSentEvent": "._models", + "aconnect_sse": "._api", + "connect_sse": "._api", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["EventSource", "SSEError", "ServerSentEvent", "aconnect_sse", "connect_sse"] diff --git a/src/webflow/core/http_sse/_api.py b/src/webflow/core/http_sse/_api.py new file mode 100644 index 0000000..f900b3b --- /dev/null +++ b/src/webflow/core/http_sse/_api.py @@ -0,0 +1,112 @@ +# This file was auto-generated by Fern from our API Definition. + +import re +from contextlib import asynccontextmanager, contextmanager +from typing import Any, AsyncGenerator, AsyncIterator, Iterator, cast + +import httpx +from ._decoders import SSEDecoder +from ._exceptions import SSEError +from ._models import ServerSentEvent + + +class EventSource: + def __init__(self, response: httpx.Response) -> None: + self._response = response + + def _check_content_type(self) -> None: + content_type = self._response.headers.get("content-type", "").partition(";")[0] + if "text/event-stream" not in content_type: + raise SSEError( + f"Expected response header Content-Type to contain 'text/event-stream', got {content_type!r}" + ) + + def _get_charset(self) -> str: + """Extract charset from Content-Type header, fallback to UTF-8.""" + content_type = self._response.headers.get("content-type", "") + + # Parse charset parameter using regex + charset_match = re.search(r"charset=([^;\s]+)", content_type, re.IGNORECASE) + if charset_match: + charset = charset_match.group(1).strip("\"'") + # Validate that it's a known encoding + try: + # Test if the charset is valid by trying to encode/decode + "test".encode(charset).decode(charset) + return charset + except (LookupError, UnicodeError): + # If charset is invalid, fall back to UTF-8 + pass + + # Default to UTF-8 if no charset specified or invalid charset + return "utf-8" + + @property + def response(self) -> httpx.Response: + return self._response + + def iter_sse(self) -> Iterator[ServerSentEvent]: + self._check_content_type() + decoder = SSEDecoder() + charset = self._get_charset() + + buffer = "" + for chunk in self._response.iter_bytes(): + # Decode chunk using detected charset + text_chunk = chunk.decode(charset, errors="replace") + buffer += text_chunk + + # Process complete lines + while "\n" in buffer: + line, buffer = buffer.split("\n", 1) + line = line.rstrip("\r") + sse = decoder.decode(line) + # when we reach a "\n\n" => line = '' + # => decoder will attempt to return an SSE Event + if sse is not None: + yield sse + + # Process any remaining data in buffer + if buffer.strip(): + line = buffer.rstrip("\r") + sse = decoder.decode(line) + if sse is not None: + yield sse + + async def aiter_sse(self) -> AsyncGenerator[ServerSentEvent, None]: + self._check_content_type() + decoder = SSEDecoder() + lines = cast(AsyncGenerator[str, None], self._response.aiter_lines()) + try: + async for line in lines: + line = line.rstrip("\n") + sse = decoder.decode(line) + if sse is not None: + yield sse + finally: + await lines.aclose() + + +@contextmanager +def connect_sse(client: httpx.Client, method: str, url: str, **kwargs: Any) -> Iterator[EventSource]: + headers = kwargs.pop("headers", {}) + headers["Accept"] = "text/event-stream" + headers["Cache-Control"] = "no-store" + + with client.stream(method, url, headers=headers, **kwargs) as response: + yield EventSource(response) + + +@asynccontextmanager +async def aconnect_sse( + client: httpx.AsyncClient, + method: str, + url: str, + **kwargs: Any, +) -> AsyncIterator[EventSource]: + headers = kwargs.pop("headers", {}) + headers["Accept"] = "text/event-stream" + headers["Cache-Control"] = "no-store" + + async with client.stream(method, url, headers=headers, **kwargs) as response: + yield EventSource(response) diff --git a/src/webflow/core/http_sse/_decoders.py b/src/webflow/core/http_sse/_decoders.py new file mode 100644 index 0000000..339b089 --- /dev/null +++ b/src/webflow/core/http_sse/_decoders.py @@ -0,0 +1,61 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import List, Optional + +from ._models import ServerSentEvent + + +class SSEDecoder: + def __init__(self) -> None: + self._event = "" + self._data: List[str] = [] + self._last_event_id = "" + self._retry: Optional[int] = None + + def decode(self, line: str) -> Optional[ServerSentEvent]: + # See: https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation # noqa: E501 + + if not line: + if not self._event and not self._data and not self._last_event_id and self._retry is None: + return None + + sse = ServerSentEvent( + event=self._event, + data="\n".join(self._data), + id=self._last_event_id, + retry=self._retry, + ) + + # NOTE: as per the SSE spec, do not reset last_event_id. + self._event = "" + self._data = [] + self._retry = None + + return sse + + if line.startswith(":"): + return None + + fieldname, _, value = line.partition(":") + + if value.startswith(" "): + value = value[1:] + + if fieldname == "event": + self._event = value + elif fieldname == "data": + self._data.append(value) + elif fieldname == "id": + if "\0" in value: + pass + else: + self._last_event_id = value + elif fieldname == "retry": + try: + self._retry = int(value) + except (TypeError, ValueError): + pass + else: + pass # Field is ignored. + + return None diff --git a/tests/__init__.py b/src/webflow/core/http_sse/_exceptions.py similarity index 51% rename from tests/__init__.py rename to src/webflow/core/http_sse/_exceptions.py index f3ea265..81605a8 100644 --- a/tests/__init__.py +++ b/src/webflow/core/http_sse/_exceptions.py @@ -1,2 +1,7 @@ # This file was auto-generated by Fern from our API Definition. +import httpx + + +class SSEError(httpx.TransportError): + pass diff --git a/src/webflow/core/http_sse/_models.py b/src/webflow/core/http_sse/_models.py new file mode 100644 index 0000000..1af57f8 --- /dev/null +++ b/src/webflow/core/http_sse/_models.py @@ -0,0 +1,17 @@ +# This file was auto-generated by Fern from our API Definition. + +import json +from dataclasses import dataclass +from typing import Any, Optional + + +@dataclass(frozen=True) +class ServerSentEvent: + event: str = "message" + data: str = "" + id: str = "" + retry: Optional[int] = None + + def json(self) -> Any: + """Parse the data field as JSON.""" + return json.loads(self.data) diff --git a/src/webflow/core/jsonable_encoder.py b/src/webflow/core/jsonable_encoder.py index 1b631e9..f8beaea 100644 --- a/src/webflow/core/jsonable_encoder.py +++ b/src/webflow/core/jsonable_encoder.py @@ -17,7 +17,6 @@ from typing import Any, Callable, Dict, List, Optional, Set, Union import pydantic - from .datetime_utils import serialize_datetime from .pydantic_utilities import ( IS_PYDANTIC_V2, @@ -31,6 +30,10 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None) -> Any: custom_encoder = custom_encoder or {} + # Generated SDKs use Ellipsis (`...`) as the sentinel value for "OMIT". + # OMIT values should be excluded from serialized payloads. + if obj is Ellipsis: + return None if custom_encoder: if type(obj) in custom_encoder: return custom_encoder[type(obj)](obj) @@ -71,6 +74,8 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any] allowed_keys = set(obj.keys()) for key, value in obj.items(): if key in allowed_keys: + if value is Ellipsis: + continue encoded_key = jsonable_encoder(key, custom_encoder=custom_encoder) encoded_value = jsonable_encoder(value, custom_encoder=custom_encoder) encoded_dict[encoded_key] = encoded_value @@ -78,6 +83,8 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any] if isinstance(obj, (list, set, frozenset, GeneratorType, tuple)): encoded_list = [] for item in obj: + if item is Ellipsis: + continue encoded_list.append(jsonable_encoder(item, custom_encoder=custom_encoder)) return encoded_list diff --git a/src/webflow/core/logging.py b/src/webflow/core/logging.py new file mode 100644 index 0000000..e5e5724 --- /dev/null +++ b/src/webflow/core/logging.py @@ -0,0 +1,107 @@ +# This file was auto-generated by Fern from our API Definition. + +import logging +import typing + +LogLevel = typing.Literal["debug", "info", "warn", "error"] + +_LOG_LEVEL_MAP: typing.Dict[LogLevel, int] = { + "debug": 1, + "info": 2, + "warn": 3, + "error": 4, +} + + +class ILogger(typing.Protocol): + def debug(self, message: str, **kwargs: typing.Any) -> None: ... + def info(self, message: str, **kwargs: typing.Any) -> None: ... + def warn(self, message: str, **kwargs: typing.Any) -> None: ... + def error(self, message: str, **kwargs: typing.Any) -> None: ... + + +class ConsoleLogger: + _logger: logging.Logger + + def __init__(self) -> None: + self._logger = logging.getLogger("fern") + if not self._logger.handlers: + handler = logging.StreamHandler() + handler.setFormatter(logging.Formatter("%(levelname)s - %(message)s")) + self._logger.addHandler(handler) + self._logger.setLevel(logging.DEBUG) + + def debug(self, message: str, **kwargs: typing.Any) -> None: + self._logger.debug(message, extra=kwargs) + + def info(self, message: str, **kwargs: typing.Any) -> None: + self._logger.info(message, extra=kwargs) + + def warn(self, message: str, **kwargs: typing.Any) -> None: + self._logger.warning(message, extra=kwargs) + + def error(self, message: str, **kwargs: typing.Any) -> None: + self._logger.error(message, extra=kwargs) + + +class LogConfig(typing.TypedDict, total=False): + level: LogLevel + logger: ILogger + silent: bool + + +class Logger: + _level: int + _logger: ILogger + _silent: bool + + def __init__(self, *, level: LogLevel, logger: ILogger, silent: bool) -> None: + self._level = _LOG_LEVEL_MAP[level] + self._logger = logger + self._silent = silent + + def _should_log(self, level: LogLevel) -> bool: + return not self._silent and self._level <= _LOG_LEVEL_MAP[level] + + def is_debug(self) -> bool: + return self._should_log("debug") + + def is_info(self) -> bool: + return self._should_log("info") + + def is_warn(self) -> bool: + return self._should_log("warn") + + def is_error(self) -> bool: + return self._should_log("error") + + def debug(self, message: str, **kwargs: typing.Any) -> None: + if self.is_debug(): + self._logger.debug(message, **kwargs) + + def info(self, message: str, **kwargs: typing.Any) -> None: + if self.is_info(): + self._logger.info(message, **kwargs) + + def warn(self, message: str, **kwargs: typing.Any) -> None: + if self.is_warn(): + self._logger.warn(message, **kwargs) + + def error(self, message: str, **kwargs: typing.Any) -> None: + if self.is_error(): + self._logger.error(message, **kwargs) + + +_default_logger: Logger = Logger(level="info", logger=ConsoleLogger(), silent=True) + + +def create_logger(config: typing.Optional[typing.Union[LogConfig, Logger]] = None) -> Logger: + if config is None: + return _default_logger + if isinstance(config, Logger): + return config + return Logger( + level=config.get("level", "info"), + logger=config.get("logger", ConsoleLogger()), + silent=config.get("silent", True), + ) diff --git a/src/webflow/core/parse_error.py b/src/webflow/core/parse_error.py new file mode 100644 index 0000000..4527c6a --- /dev/null +++ b/src/webflow/core/parse_error.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict, Optional + + +class ParsingError(Exception): + """ + Raised when the SDK fails to parse/validate a response from the server. + This typically indicates that the server returned a response whose shape + does not match the expected schema. + """ + + headers: Optional[Dict[str, str]] + status_code: Optional[int] + body: Any + cause: Optional[Exception] + + def __init__( + self, + *, + headers: Optional[Dict[str, str]] = None, + status_code: Optional[int] = None, + body: Any = None, + cause: Optional[Exception] = None, + ) -> None: + self.headers = headers + self.status_code = status_code + self.body = body + self.cause = cause + super().__init__() + if cause is not None: + self.__cause__ = cause + + def __str__(self) -> str: + cause_str = f", cause: {self.cause}" if self.cause is not None else "" + return f"headers: {self.headers}, status_code: {self.status_code}, body: {self.body}{cause_str}" diff --git a/src/webflow/core/pydantic_utilities.py b/src/webflow/core/pydantic_utilities.py index ee8f0e4..831aadc 100644 --- a/src/webflow/core/pydantic_utilities.py +++ b/src/webflow/core/pydantic_utilities.py @@ -2,90 +2,349 @@ # nopycln: file import datetime as dt -import typing +import inspect +import json +import logging from collections import defaultdict +from dataclasses import asdict +from typing import ( + TYPE_CHECKING, + Any, + Callable, + ClassVar, + Dict, + List, + Mapping, + Optional, + Set, + Tuple, + Type, + TypeVar, + Union, + cast, +) +import pydantic import typing_extensions -import pydantic +_logger = logging.getLogger(__name__) -from .datetime_utils import serialize_datetime -from .serialization import convert_and_respect_annotation_metadata +if TYPE_CHECKING: + from .http_sse._models import ServerSentEvent IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.") if IS_PYDANTIC_V2: - # isort will try to reformat the comments on these imports, which breaks mypy - # isort: off - from pydantic.v1.datetime_parse import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2 - parse_date as parse_date, - ) - from pydantic.v1.datetime_parse import ( # pyright: ignore[reportMissingImports] # Pydantic v2 - parse_datetime as parse_datetime, - ) - from pydantic.v1.json import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2 - ENCODERS_BY_TYPE as encoders_by_type, - ) - from pydantic.v1.typing import ( # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2 - get_args as get_args, - ) - from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2 - get_origin as get_origin, - ) - from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2 - is_literal_type as is_literal_type, - ) - from pydantic.v1.typing import ( # pyright: ignore[reportMissingImports] # Pydantic v2 - is_union as is_union, - ) - from pydantic.v1.fields import ModelField as ModelField # type: ignore # pyright: ignore[reportMissingImports] # Pydantic v2 + import warnings + + _datetime_adapter = pydantic.TypeAdapter(dt.datetime) # type: ignore[attr-defined] + _date_adapter = pydantic.TypeAdapter(dt.date) # type: ignore[attr-defined] + + def parse_datetime(value: Any) -> dt.datetime: # type: ignore[misc] + if isinstance(value, dt.datetime): + return value + return _datetime_adapter.validate_python(value) + + def parse_date(value: Any) -> dt.date: # type: ignore[misc] + if isinstance(value, dt.datetime): + return value.date() + if isinstance(value, dt.date): + return value + return _date_adapter.validate_python(value) + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", UserWarning) + from pydantic.v1.fields import ModelField as ModelField + from pydantic.v1.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[attr-defined] + from pydantic.v1.typing import get_args as get_args + from pydantic.v1.typing import get_origin as get_origin + from pydantic.v1.typing import is_literal_type as is_literal_type + from pydantic.v1.typing import is_union as is_union else: - from pydantic.datetime_parse import parse_date as parse_date # type: ignore # Pydantic v1 - from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore # Pydantic v1 - from pydantic.fields import ModelField as ModelField # type: ignore # Pydantic v1 - from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore # Pydantic v1 - from pydantic.typing import get_args as get_args # type: ignore # Pydantic v1 - from pydantic.typing import get_origin as get_origin # type: ignore # Pydantic v1 - from pydantic.typing import is_literal_type as is_literal_type # type: ignore # Pydantic v1 - from pydantic.typing import is_union as is_union # type: ignore # Pydantic v1 - - # isort: on - - -T = typing.TypeVar("T") -Model = typing.TypeVar("Model", bound=pydantic.BaseModel) + from pydantic.datetime_parse import parse_date as parse_date # type: ignore[no-redef] + from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore[no-redef] + from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef] + from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[no-redef] + from pydantic.typing import get_args as get_args # type: ignore[no-redef] + from pydantic.typing import get_origin as get_origin # type: ignore[no-redef] + from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef] + from pydantic.typing import is_union as is_union # type: ignore[no-redef] +from .datetime_utils import serialize_datetime +from .serialization import convert_and_respect_annotation_metadata +from typing_extensions import TypeAlias + +T = TypeVar("T") +Model = TypeVar("Model", bound=pydantic.BaseModel) + + +def _get_discriminator_and_variants(type_: Type[Any]) -> Tuple[Optional[str], Optional[List[Type[Any]]]]: + """ + Extract the discriminator field name and union variants from a discriminated union type. + Supports Annotated[Union[...], Field(discriminator=...)] patterns. + Returns (discriminator, variants) or (None, None) if not a discriminated union. + """ + origin = typing_extensions.get_origin(type_) + + if origin is typing_extensions.Annotated: + args = typing_extensions.get_args(type_) + if len(args) >= 2: + inner_type = args[0] + # Check annotations for discriminator + discriminator = None + for annotation in args[1:]: + if hasattr(annotation, "discriminator"): + discriminator = getattr(annotation, "discriminator", None) + break + + if discriminator: + inner_origin = typing_extensions.get_origin(inner_type) + if inner_origin is Union: + variants = list(typing_extensions.get_args(inner_type)) + return discriminator, variants + return None, None + + +def _get_field_annotation(model: Type[Any], field_name: str) -> Optional[Type[Any]]: + """Get the type annotation of a field from a Pydantic model.""" + if IS_PYDANTIC_V2: + fields = getattr(model, "model_fields", {}) + field_info = fields.get(field_name) + if field_info: + return cast(Optional[Type[Any]], field_info.annotation) + else: + fields = getattr(model, "__fields__", {}) + field_info = fields.get(field_name) + if field_info: + return cast(Optional[Type[Any]], field_info.outer_type_) + return None + + +def _find_variant_by_discriminator( + variants: List[Type[Any]], + discriminator: str, + discriminator_value: Any, +) -> Optional[Type[Any]]: + """Find the union variant that matches the discriminator value.""" + for variant in variants: + if not (inspect.isclass(variant) and issubclass(variant, pydantic.BaseModel)): + continue + + disc_annotation = _get_field_annotation(variant, discriminator) + if disc_annotation and is_literal_type(disc_annotation): + literal_args = get_args(disc_annotation) + if literal_args and literal_args[0] == discriminator_value: + return variant + return None + + +def _is_string_type(type_: Type[Any]) -> bool: + """Check if a type is str or Optional[str].""" + if type_ is str: + return True + + origin = typing_extensions.get_origin(type_) + if origin is Union: + args = typing_extensions.get_args(type_) + # Optional[str] = Union[str, None] + non_none_args = [a for a in args if a is not type(None)] + if len(non_none_args) == 1 and non_none_args[0] is str: + return True + + return False + + +def parse_sse_obj(sse: "ServerSentEvent", type_: Type[T]) -> T: + """ + Parse a ServerSentEvent into the appropriate type. + + Handles two scenarios based on where the discriminator field is located: + + 1. Data-level discrimination: The discriminator (e.g., 'type') is inside the 'data' payload. + The union describes the data content, not the SSE envelope. + -> Returns: json.loads(data) parsed into the type + + Example: ChatStreamResponse with discriminator='type' + Input: ServerSentEvent(event="message", data='{"type": "content-delta", ...}', id="") + Output: ContentDeltaEvent (parsed from data, SSE envelope stripped) + + 2. Event-level discrimination: The discriminator (e.g., 'event') is at the SSE event level. + The union describes the full SSE event structure. + -> Returns: SSE envelope with 'data' field JSON-parsed only if the variant expects non-string + + Example: JobStreamResponse with discriminator='event' + Input: ServerSentEvent(event="ERROR", data='{"code": "FAILED", ...}', id="123") + Output: JobStreamResponse_Error with data as ErrorData object + + But for variants where data is str (like STATUS_UPDATE): + Input: ServerSentEvent(event="STATUS_UPDATE", data='{"status": "processing"}', id="1") + Output: JobStreamResponse_StatusUpdate with data as string (not parsed) + + Args: + sse: The ServerSentEvent object to parse + type_: The target discriminated union type + + Returns: + The parsed object of type T + + Note: + This function is only available in SDK contexts where http_sse module exists. + """ + sse_event = asdict(sse) + discriminator, variants = _get_discriminator_and_variants(type_) + + if discriminator is None or variants is None: + # Not a discriminated union - parse the data field as JSON + data_value = sse_event.get("data") + if isinstance(data_value, str) and data_value: + try: + parsed_data = json.loads(data_value) + return parse_obj_as(type_, parsed_data) + except json.JSONDecodeError as e: + _logger.warning( + "Failed to parse SSE data field as JSON: %s, data: %s", + e, + data_value[:100] if len(data_value) > 100 else data_value, + ) + return parse_obj_as(type_, sse_event) + + data_value = sse_event.get("data") + + # Check if discriminator is at the top level (event-level discrimination) + if discriminator in sse_event: + # Case 2: Event-level discrimination + # Find the matching variant to check if 'data' field needs JSON parsing + disc_value = sse_event.get(discriminator) + matching_variant = _find_variant_by_discriminator(variants, discriminator, disc_value) + + if matching_variant is not None: + # Check what type the variant expects for 'data' + data_type = _get_field_annotation(matching_variant, "data") + if data_type is not None and not _is_string_type(data_type): + # Variant expects non-string data - parse JSON + if isinstance(data_value, str) and data_value: + try: + parsed_data = json.loads(data_value) + new_object = dict(sse_event) + new_object["data"] = parsed_data + return parse_obj_as(type_, new_object) + except json.JSONDecodeError as e: + _logger.warning( + "Failed to parse SSE data field as JSON for event-level discrimination: %s, data: %s", + e, + data_value[:100] if len(data_value) > 100 else data_value, + ) + # Either no matching variant, data is string type, or JSON parse failed + return parse_obj_as(type_, sse_event) -def parse_obj_as(type_: typing.Type[T], object_: typing.Any) -> T: - dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read") + else: + # Case 1: Data-level discrimination + # The discriminator is inside the data payload - extract and parse data only + if isinstance(data_value, str) and data_value: + try: + parsed_data = json.loads(data_value) + return parse_obj_as(type_, parsed_data) + except json.JSONDecodeError as e: + _logger.warning( + "Failed to parse SSE data field as JSON for data-level discrimination: %s, data: %s", + e, + data_value[:100] if len(data_value) > 100 else data_value, + ) + return parse_obj_as(type_, sse_event) + + +def parse_obj_as(type_: Type[T], object_: Any) -> T: + # convert_and_respect_annotation_metadata is required for TypedDict aliasing. + # + # For Pydantic models, whether we should pre-dealias depends on how the model encodes aliasing: + # - If the model uses real Pydantic aliases (pydantic.Field(alias=...)), then we must pass wire keys through + # unchanged so Pydantic can validate them. + # - If the model encodes aliasing only via FieldMetadata annotations, then we MUST pre-dealias because Pydantic + # will not recognize those aliases during validation. + if inspect.isclass(type_) and issubclass(type_, pydantic.BaseModel): + has_pydantic_aliases = False + if IS_PYDANTIC_V2: + for field_name, field_info in getattr(type_, "model_fields", {}).items(): # type: ignore[attr-defined] + alias = getattr(field_info, "alias", None) + if alias is not None and alias != field_name: + has_pydantic_aliases = True + break + else: + for field in getattr(type_, "__fields__", {}).values(): + alias = getattr(field, "alias", None) + name = getattr(field, "name", None) + if alias is not None and name is not None and alias != name: + has_pydantic_aliases = True + break + + dealiased_object = ( + object_ + if has_pydantic_aliases + else convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read") + ) + else: + dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read") if IS_PYDANTIC_V2: - adapter = pydantic.TypeAdapter(type_) # type: ignore # Pydantic v2 + adapter = pydantic.TypeAdapter(type_) # type: ignore[attr-defined] return adapter.validate_python(dealiased_object) - else: - return pydantic.parse_obj_as(type_, dealiased_object) + return pydantic.parse_obj_as(type_, dealiased_object) -def to_jsonable_with_fallback( - obj: typing.Any, fallback_serializer: typing.Callable[[typing.Any], typing.Any] -) -> typing.Any: +def to_jsonable_with_fallback(obj: Any, fallback_serializer: Callable[[Any], Any]) -> Any: if IS_PYDANTIC_V2: from pydantic_core import to_jsonable_python return to_jsonable_python(obj, fallback=fallback_serializer) - else: - return fallback_serializer(obj) + return fallback_serializer(obj) class UniversalBaseModel(pydantic.BaseModel): if IS_PYDANTIC_V2: - model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( - # Allow fields begining with `model_` to be used in the model + model_config: ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( # type: ignore[typeddict-unknown-key] + # Allow fields beginning with `model_` to be used in the model protected_namespaces=(), - ) # type: ignore # Pydantic v2 - - @pydantic.model_serializer(mode="wrap", when_used="json") # type: ignore # Pydantic v2 - def serialize_model(self, handler: pydantic.SerializerFunctionWrapHandler) -> typing.Any: # type: ignore # Pydantic v2 - serialized = handler(self) + ) + + @pydantic.model_validator(mode="before") # type: ignore[attr-defined] + @classmethod + def _coerce_field_names_to_aliases(cls, data: Any) -> Any: + """ + Accept Python field names in input by rewriting them to their Pydantic aliases, + while avoiding silent collisions when a key could refer to multiple fields. + """ + if not isinstance(data, Mapping): + return data + + fields = getattr(cls, "model_fields", {}) # type: ignore[attr-defined] + name_to_alias: Dict[str, str] = {} + alias_to_name: Dict[str, str] = {} + + for name, field_info in fields.items(): + alias = getattr(field_info, "alias", None) or name + name_to_alias[name] = alias + if alias != name: + alias_to_name[alias] = name + + # Detect ambiguous keys: a key that is an alias for one field and a name for another. + ambiguous_keys = set(alias_to_name.keys()).intersection(set(name_to_alias.keys())) + for key in ambiguous_keys: + if key in data and name_to_alias[key] not in data: + raise ValueError( + f"Ambiguous input key '{key}': it is both a field name and an alias. " + "Provide the explicit alias key to disambiguate." + ) + + original_keys = set(data.keys()) + rewritten: Dict[str, Any] = dict(data) + for name, alias in name_to_alias.items(): + if alias != name and name in original_keys and alias not in rewritten: + rewritten[alias] = rewritten.pop(name) + + return rewritten + + @pydantic.model_serializer(mode="plain", when_used="json") # type: ignore[attr-defined] + def serialize_model(self) -> Any: # type: ignore[name-defined] + serialized = self.dict() # type: ignore[attr-defined] data = {k: serialize_datetime(v) if isinstance(v, dt.datetime) else v for k, v in serialized.items()} return data @@ -95,60 +354,88 @@ class Config: smart_union = True json_encoders = {dt.datetime: serialize_datetime} + @pydantic.root_validator(pre=True) + def _coerce_field_names_to_aliases(cls, values: Any) -> Any: + """ + Pydantic v1 equivalent of _coerce_field_names_to_aliases. + """ + if not isinstance(values, Mapping): + return values + + fields = getattr(cls, "__fields__", {}) + name_to_alias: Dict[str, str] = {} + alias_to_name: Dict[str, str] = {} + + for name, field in fields.items(): + alias = getattr(field, "alias", None) or name + name_to_alias[name] = alias + if alias != name: + alias_to_name[alias] = name + + ambiguous_keys = set(alias_to_name.keys()).intersection(set(name_to_alias.keys())) + for key in ambiguous_keys: + if key in values and name_to_alias[key] not in values: + raise ValueError( + f"Ambiguous input key '{key}': it is both a field name and an alias. " + "Provide the explicit alias key to disambiguate." + ) + + original_keys = set(values.keys()) + rewritten: Dict[str, Any] = dict(values) + for name, alias in name_to_alias.items(): + if alias != name and name in original_keys and alias not in rewritten: + rewritten[alias] = rewritten.pop(name) + + return rewritten + @classmethod - def model_construct( - cls: typing.Type["Model"], _fields_set: typing.Optional[typing.Set[str]] = None, **values: typing.Any - ) -> "Model": + def model_construct(cls: Type["Model"], _fields_set: Optional[Set[str]] = None, **values: Any) -> "Model": dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read") return cls.construct(_fields_set, **dealiased_object) @classmethod - def construct( - cls: typing.Type["Model"], _fields_set: typing.Optional[typing.Set[str]] = None, **values: typing.Any - ) -> "Model": + def construct(cls: Type["Model"], _fields_set: Optional[Set[str]] = None, **values: Any) -> "Model": dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read") if IS_PYDANTIC_V2: - return super().model_construct(_fields_set, **dealiased_object) # type: ignore # Pydantic v2 - else: - return super().construct(_fields_set, **dealiased_object) + return super().model_construct(_fields_set, **dealiased_object) # type: ignore[misc] + return super().construct(_fields_set, **dealiased_object) - def json(self, **kwargs: typing.Any) -> str: - kwargs_with_defaults: typing.Any = { + def json(self, **kwargs: Any) -> str: + kwargs_with_defaults = { "by_alias": True, "exclude_unset": True, **kwargs, } if IS_PYDANTIC_V2: - return super().model_dump_json(**kwargs_with_defaults) # type: ignore # Pydantic v2 - else: - return super().json(**kwargs_with_defaults) + return super().model_dump_json(**kwargs_with_defaults) # type: ignore[misc] + return super().json(**kwargs_with_defaults) - def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: + def dict(self, **kwargs: Any) -> Dict[str, Any]: """ Override the default dict method to `exclude_unset` by default. This function patches `exclude_unset` to work include fields within non-None default values. """ - # Note: the logic here is multi-plexed given the levers exposed in Pydantic V1 vs V2 + # Note: the logic here is multiplexed given the levers exposed in Pydantic V1 vs V2 # Pydantic V1's .dict can be extremely slow, so we do not want to call it twice. # # We'd ideally do the same for Pydantic V2, but it shells out to a library to serialize models # that we have less control over, and this is less intrusive than custom serializers for now. if IS_PYDANTIC_V2: - kwargs_with_defaults_exclude_unset: typing.Any = { + kwargs_with_defaults_exclude_unset = { **kwargs, "by_alias": True, "exclude_unset": True, "exclude_none": False, } - kwargs_with_defaults_exclude_none: typing.Any = { + kwargs_with_defaults_exclude_none = { **kwargs, "by_alias": True, "exclude_none": True, "exclude_unset": False, } dict_dump = deep_union_pydantic_dicts( - super().model_dump(**kwargs_with_defaults_exclude_unset), # type: ignore # Pydantic v2 - super().model_dump(**kwargs_with_defaults_exclude_none), # type: ignore # Pydantic v2 + super().model_dump(**kwargs_with_defaults_exclude_unset), # type: ignore[misc] + super().model_dump(**kwargs_with_defaults_exclude_none), # type: ignore[misc] ) else: @@ -168,7 +455,7 @@ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: if default is not None: self.__fields_set__.add(name) - kwargs_with_defaults_exclude_unset_include_fields: typing.Any = { + kwargs_with_defaults_exclude_unset_include_fields = { "by_alias": True, "exclude_unset": True, "include": _fields_set, @@ -177,15 +464,16 @@ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: dict_dump = super().dict(**kwargs_with_defaults_exclude_unset_include_fields) - return convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write") + return cast( + Dict[str, Any], + convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write"), + ) -def _union_list_of_pydantic_dicts( - source: typing.List[typing.Any], destination: typing.List[typing.Any] -) -> typing.List[typing.Any]: - converted_list: typing.List[typing.Any] = [] +def _union_list_of_pydantic_dicts(source: List[Any], destination: List[Any]) -> List[Any]: + converted_list: List[Any] = [] for i, item in enumerate(source): - destination_value = destination[i] # type: ignore + destination_value = destination[i] if isinstance(item, dict): converted_list.append(deep_union_pydantic_dicts(item, destination_value)) elif isinstance(item, list): @@ -195,9 +483,7 @@ def _union_list_of_pydantic_dicts( return converted_list -def deep_union_pydantic_dicts( - source: typing.Dict[str, typing.Any], destination: typing.Dict[str, typing.Any] -) -> typing.Dict[str, typing.Any]: +def deep_union_pydantic_dicts(source: Dict[str, Any], destination: Dict[str, Any]) -> Dict[str, Any]: for key, value in source.items(): node = destination.setdefault(key, {}) if isinstance(value, dict): @@ -215,18 +501,16 @@ def deep_union_pydantic_dicts( if IS_PYDANTIC_V2: - class V2RootModel(UniversalBaseModel, pydantic.RootModel): # type: ignore # Pydantic v2 + class V2RootModel(UniversalBaseModel, pydantic.RootModel): # type: ignore[misc, name-defined, type-arg] pass - UniversalRootModel: typing_extensions.TypeAlias = V2RootModel # type: ignore + UniversalRootModel: TypeAlias = V2RootModel # type: ignore[misc] else: - UniversalRootModel: typing_extensions.TypeAlias = UniversalBaseModel # type: ignore + UniversalRootModel: TypeAlias = UniversalBaseModel # type: ignore[misc, no-redef] -def encode_by_type(o: typing.Any) -> typing.Any: - encoders_by_class_tuples: typing.Dict[typing.Callable[[typing.Any], typing.Any], typing.Tuple[typing.Any, ...]] = ( - defaultdict(tuple) - ) +def encode_by_type(o: Any) -> Any: + encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(tuple) for type_, encoder in encoders_by_type.items(): encoders_by_class_tuples[encoder] += (type_,) @@ -237,54 +521,51 @@ def encode_by_type(o: typing.Any) -> typing.Any: return encoder(o) -def update_forward_refs(model: typing.Type["Model"], **localns: typing.Any) -> None: +def update_forward_refs(model: Type["Model"], **localns: Any) -> None: if IS_PYDANTIC_V2: - model.model_rebuild(raise_errors=False) # type: ignore # Pydantic v2 + model.model_rebuild(raise_errors=False) # type: ignore[attr-defined] else: model.update_forward_refs(**localns) # Mirrors Pydantic's internal typing -AnyCallable = typing.Callable[..., typing.Any] +AnyCallable = Callable[..., Any] def universal_root_validator( pre: bool = False, -) -> typing.Callable[[AnyCallable], AnyCallable]: +) -> Callable[[AnyCallable], AnyCallable]: def decorator(func: AnyCallable) -> AnyCallable: if IS_PYDANTIC_V2: - return pydantic.model_validator(mode="before" if pre else "after")(func) # type: ignore # Pydantic v2 - else: - return pydantic.root_validator(pre=pre)(func) # type: ignore # Pydantic v1 + # In Pydantic v2, for RootModel we always use "before" mode + # The custom validators transform the input value before the model is created + return cast(AnyCallable, pydantic.model_validator(mode="before")(func)) # type: ignore[attr-defined] + return cast(AnyCallable, pydantic.root_validator(pre=pre)(func)) # type: ignore[call-overload] return decorator -def universal_field_validator(field_name: str, pre: bool = False) -> typing.Callable[[AnyCallable], AnyCallable]: +def universal_field_validator(field_name: str, pre: bool = False) -> Callable[[AnyCallable], AnyCallable]: def decorator(func: AnyCallable) -> AnyCallable: if IS_PYDANTIC_V2: - return pydantic.field_validator(field_name, mode="before" if pre else "after")(func) # type: ignore # Pydantic v2 - else: - return pydantic.validator(field_name, pre=pre)(func) # type: ignore # Pydantic v1 + return cast(AnyCallable, pydantic.field_validator(field_name, mode="before" if pre else "after")(func)) # type: ignore[attr-defined] + return cast(AnyCallable, pydantic.validator(field_name, pre=pre)(func)) return decorator -PydanticField = typing.Union[ModelField, pydantic.fields.FieldInfo] +PydanticField = Union[ModelField, pydantic.fields.FieldInfo] -def _get_model_fields( - model: typing.Type["Model"], -) -> typing.Mapping[str, PydanticField]: +def _get_model_fields(model: Type["Model"]) -> Mapping[str, PydanticField]: if IS_PYDANTIC_V2: - return model.model_fields # type: ignore # Pydantic v2 - else: - return model.__fields__ # type: ignore # Pydantic v1 + return cast(Mapping[str, PydanticField], model.model_fields) # type: ignore[attr-defined] + return cast(Mapping[str, PydanticField], model.__fields__) -def _get_field_default(field: PydanticField) -> typing.Any: +def _get_field_default(field: PydanticField) -> Any: try: - value = field.get_default() # type: ignore # Pydantic < v1.10.15 + value = field.get_default() # type: ignore[union-attr] except: value = field.default if IS_PYDANTIC_V2: diff --git a/src/webflow/core/serialization.py b/src/webflow/core/serialization.py index cb5dcbf..c36e865 100644 --- a/src/webflow/core/serialization.py +++ b/src/webflow/core/serialization.py @@ -4,9 +4,8 @@ import inspect import typing -import typing_extensions - import pydantic +import typing_extensions class FieldMetadata: @@ -161,7 +160,12 @@ def _convert_mapping( direction: typing.Literal["read", "write"], ) -> typing.Mapping[str, object]: converted_object: typing.Dict[str, object] = {} - annotations = typing_extensions.get_type_hints(expected_type, include_extras=True) + try: + annotations = typing_extensions.get_type_hints(expected_type, include_extras=True) + except NameError: + # The TypedDict contains a circular reference, so + # we use the __annotations__ attribute directly. + annotations = getattr(expected_type, "__annotations__", {}) aliases_to_field_names = _get_alias_to_field_name(annotations) for key, value in object_.items(): if direction == "read" and key in aliases_to_field_names: diff --git a/src/webflow/errors/__init__.py b/src/webflow/errors/__init__.py index 3b6de05..bd5f618 100644 --- a/src/webflow/errors/__init__.py +++ b/src/webflow/errors/__init__.py @@ -1,12 +1,49 @@ # This file was auto-generated by Fern from our API Definition. -from .bad_request_error import BadRequestError -from .conflict_error import ConflictError -from .forbidden_error import ForbiddenError -from .internal_server_error import InternalServerError -from .not_found_error import NotFoundError -from .too_many_requests_error import TooManyRequestsError -from .unauthorized_error import UnauthorizedError +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .bad_request_error import BadRequestError + from .conflict_error import ConflictError + from .forbidden_error import ForbiddenError + from .internal_server_error import InternalServerError + from .not_found_error import NotFoundError + from .too_many_requests_error import TooManyRequestsError + from .unauthorized_error import UnauthorizedError +_dynamic_imports: typing.Dict[str, str] = { + "BadRequestError": ".bad_request_error", + "ConflictError": ".conflict_error", + "ForbiddenError": ".forbidden_error", + "InternalServerError": ".internal_server_error", + "NotFoundError": ".not_found_error", + "TooManyRequestsError": ".too_many_requests_error", + "UnauthorizedError": ".unauthorized_error", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "BadRequestError", diff --git a/src/webflow/errors/bad_request_error.py b/src/webflow/errors/bad_request_error.py index 9c13c61..ec78e26 100644 --- a/src/webflow/errors/bad_request_error.py +++ b/src/webflow/errors/bad_request_error.py @@ -1,9 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.api_error import ApiError import typing +from ..core.api_error import ApiError + class BadRequestError(ApiError): - def __init__(self, body: typing.Optional[typing.Any]): - super().__init__(status_code=400, body=body) + def __init__(self, body: typing.Any, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=400, headers=headers, body=body) diff --git a/src/webflow/errors/conflict_error.py b/src/webflow/errors/conflict_error.py index 666bd2b..be04e01 100644 --- a/src/webflow/errors/conflict_error.py +++ b/src/webflow/errors/conflict_error.py @@ -1,9 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.api_error import ApiError import typing +from ..core.api_error import ApiError + class ConflictError(ApiError): - def __init__(self, body: typing.Optional[typing.Any]): - super().__init__(status_code=409, body=body) + def __init__(self, body: typing.Any, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=409, headers=headers, body=body) diff --git a/src/webflow/errors/forbidden_error.py b/src/webflow/errors/forbidden_error.py index d17eb4b..07d7e45 100644 --- a/src/webflow/errors/forbidden_error.py +++ b/src/webflow/errors/forbidden_error.py @@ -1,9 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.api_error import ApiError import typing +from ..core.api_error import ApiError + class ForbiddenError(ApiError): - def __init__(self, body: typing.Optional[typing.Any]): - super().__init__(status_code=403, body=body) + def __init__(self, body: typing.Any, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=403, headers=headers, body=body) diff --git a/src/webflow/errors/internal_server_error.py b/src/webflow/errors/internal_server_error.py index c5dcb4a..2c41ca5 100644 --- a/src/webflow/errors/internal_server_error.py +++ b/src/webflow/errors/internal_server_error.py @@ -1,9 +1,11 @@ # This file was auto-generated by Fern from our API Definition. +import typing + from ..core.api_error import ApiError from ..types.error import Error class InternalServerError(ApiError): - def __init__(self, body: Error): - super().__init__(status_code=500, body=body) + def __init__(self, body: Error, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=500, headers=headers, body=body) diff --git a/src/webflow/errors/not_found_error.py b/src/webflow/errors/not_found_error.py index 307aa67..e7ed720 100644 --- a/src/webflow/errors/not_found_error.py +++ b/src/webflow/errors/not_found_error.py @@ -1,9 +1,11 @@ # This file was auto-generated by Fern from our API Definition. +import typing + from ..core.api_error import ApiError from ..types.error import Error class NotFoundError(ApiError): - def __init__(self, body: Error): - super().__init__(status_code=404, body=body) + def __init__(self, body: Error, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=404, headers=headers, body=body) diff --git a/src/webflow/errors/too_many_requests_error.py b/src/webflow/errors/too_many_requests_error.py index c2b3b10..a0743ee 100644 --- a/src/webflow/errors/too_many_requests_error.py +++ b/src/webflow/errors/too_many_requests_error.py @@ -1,9 +1,11 @@ # This file was auto-generated by Fern from our API Definition. +import typing + from ..core.api_error import ApiError from ..types.error import Error class TooManyRequestsError(ApiError): - def __init__(self, body: Error): - super().__init__(status_code=429, body=body) + def __init__(self, body: Error, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=429, headers=headers, body=body) diff --git a/src/webflow/errors/unauthorized_error.py b/src/webflow/errors/unauthorized_error.py index bba82e4..2345489 100644 --- a/src/webflow/errors/unauthorized_error.py +++ b/src/webflow/errors/unauthorized_error.py @@ -1,9 +1,11 @@ # This file was auto-generated by Fern from our API Definition. +import typing + from ..core.api_error import ApiError from ..types.error import Error class UnauthorizedError(ApiError): - def __init__(self, body: Error): - super().__init__(status_code=401, body=body) + def __init__(self, body: Error, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=401, headers=headers, body=body) diff --git a/src/webflow/resources/__init__.py b/src/webflow/resources/__init__.py index eb58716..7eea249 100644 --- a/src/webflow/resources/__init__.py +++ b/src/webflow/resources/__init__.py @@ -1,32 +1,97 @@ # This file was auto-generated by Fern from our API Definition. -from . import ( - assets, - collections, - components, - ecommerce, - forms, - inventory, - orders, - pages, - products, - scripts, - sites, - token, - webhooks, - workspaces, -) -from .components import ( - ComponentDomWriteNodesItem, - ComponentPropertiesWritePropertiesItem, - ComponentsUpdateContentResponse, - ComponentsUpdatePropertiesResponse, -) -from .inventory import EcommInventoryChangedPayload, InventoryUpdateRequestInventoryType -from .orders import OrdersListRequestStatus, OrdersRefundRequestReason -from .pages import PageDomWriteNodesItem, PageMetadataWriteOpenGraph, PageMetadataWriteSeo, UpdateStaticContentResponse -from .products import ProductSkuCreateProduct, ProductSkuCreateSku, ProductsCreateSkuResponse -from .sites import SitesPublishResponse +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from . import ( + assets, + collections, + components, + ecommerce, + forms, + inventory, + orders, + pages, + products, + scripts, + sites, + token, + webhooks, + workspaces, + ) + from .components import ( + ComponentDomWriteNodesItem, + ComponentPropertiesWritePropertiesItem, + ComponentsUpdateContentResponse, + ComponentsUpdatePropertiesResponse, + ) + from .inventory import EcommInventoryChangedPayload, InventoryUpdateRequestInventoryType + from .orders import OrdersListRequestStatus, OrdersRefundRequestReason + from .pages import ( + PageDomWriteNodesItem, + PageMetadataWriteOpenGraph, + PageMetadataWriteSeo, + UpdateStaticContentResponse, + ) + from .products import ProductSkuCreateProduct, ProductSkuCreateSku, ProductsCreateSkuResponse + from .sites import SitesPublishResponse +_dynamic_imports: typing.Dict[str, str] = { + "ComponentDomWriteNodesItem": ".components", + "ComponentPropertiesWritePropertiesItem": ".components", + "ComponentsUpdateContentResponse": ".components", + "ComponentsUpdatePropertiesResponse": ".components", + "EcommInventoryChangedPayload": ".inventory", + "InventoryUpdateRequestInventoryType": ".inventory", + "OrdersListRequestStatus": ".orders", + "OrdersRefundRequestReason": ".orders", + "PageDomWriteNodesItem": ".pages", + "PageMetadataWriteOpenGraph": ".pages", + "PageMetadataWriteSeo": ".pages", + "ProductSkuCreateProduct": ".products", + "ProductSkuCreateSku": ".products", + "ProductsCreateSkuResponse": ".products", + "SitesPublishResponse": ".sites", + "UpdateStaticContentResponse": ".pages", + "assets": ".assets", + "collections": ".collections", + "components": ".components", + "ecommerce": ".ecommerce", + "forms": ".forms", + "inventory": ".inventory", + "orders": ".orders", + "pages": ".pages", + "products": ".products", + "scripts": ".scripts", + "sites": ".sites", + "token": ".token", + "webhooks": ".webhooks", + "workspaces": ".workspaces", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "ComponentDomWriteNodesItem", diff --git a/src/webflow/resources/assets/__init__.py b/src/webflow/resources/assets/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/assets/__init__.py +++ b/src/webflow/resources/assets/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/assets/client.py b/src/webflow/resources/assets/client.py index d2723f9..ae22ab4 100644 --- a/src/webflow/resources/assets/client.py +++ b/src/webflow/resources/assets/client.py @@ -1,24 +1,15 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ...core.client_wrapper import SyncClientWrapper + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions -from ...types.assets import Assets -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.not_found_error import NotFoundError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ...types.asset_upload import AssetUpload from ...types.asset import Asset -from ...types.asset_folder_list import AssetFolderList from ...types.asset_folder import AssetFolder -from ...core.client_wrapper import AsyncClientWrapper +from ...types.asset_folder_list import AssetFolderList +from ...types.asset_upload import AssetUpload +from ...types.assets import Assets +from .raw_client import AsyncRawAssetsClient, RawAssetsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -26,7 +17,18 @@ class AssetsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawAssetsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawAssetsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawAssetsClient + """ + return self._raw_client def list( self, @@ -73,79 +75,8 @@ def list( limit=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/assets", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "offset": offset, - "limit": limit, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Assets, - parse_obj_as( - type_=Assets, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.list(site_id, offset=offset, limit=limit, request_options=request_options) + return _response.data def create( self, @@ -205,84 +136,14 @@ def create( file_hash="3c7d87c9575702bc3b1e991f4d3c638e", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/assets", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "fileName": file_name, - "fileHash": file_hash, - "parentFolder": parent_folder, - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.create( + site_id, + file_name=file_name, + file_hash=file_hash, + parent_folder=parent_folder, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AssetUpload, - parse_obj_as( - type_=AssetUpload, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Asset: """ @@ -314,75 +175,8 @@ def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] asset_id="580e63fc8c9a982ac9b8b745", ) """ - _response = self._client_wrapper.httpx_client.request( - f"assets/{jsonable_encoder(asset_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Asset, - parse_obj_as( - type_=Asset, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get(asset_id, request_options=request_options) + return _response.data def delete(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ @@ -413,69 +207,8 @@ def delete(self, asset_id: str, *, request_options: typing.Optional[RequestOptio asset_id="580e63fc8c9a982ac9b8b745", ) """ - _response = self._client_wrapper.httpx_client.request( - f"assets/{jsonable_encoder(asset_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete(asset_id, request_options=request_options) + return _response.data def update( self, @@ -520,83 +253,10 @@ def update( asset_id="580e63fc8c9a982ac9b8b745", ) """ - _response = self._client_wrapper.httpx_client.request( - f"assets/{jsonable_encoder(asset_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "localeId": locale_id, - "displayName": display_name, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.update( + asset_id, locale_id=locale_id, display_name=display_name, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Asset, - parse_obj_as( - type_=Asset, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def list_folders(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AssetFolderList: """ @@ -628,75 +288,8 @@ def list_folders(self, site_id: str, *, request_options: typing.Optional[Request site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/asset_folders", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AssetFolderList, - parse_obj_as( - type_=AssetFolderList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.list_folders(site_id, request_options=request_options) + return _response.data def create_folder( self, @@ -742,83 +335,10 @@ def create_folder( display_name="my asset folder", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/asset_folders", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "displayName": display_name, - "parentFolder": parent_folder, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.create_folder( + site_id, display_name=display_name, parent_folder=parent_folder, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AssetFolder, - parse_obj_as( - type_=AssetFolder, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get_folder( self, asset_folder_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -852,80 +372,24 @@ def get_folder( asset_folder_id="6390c49774a71f0e3c1a08ee", ) """ - _response = self._client_wrapper.httpx_client.request( - f"asset_folders/{jsonable_encoder(asset_folder_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AssetFolder, - parse_obj_as( - type_=AssetFolder, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get_folder(asset_folder_id, request_options=request_options) + return _response.data class AsyncAssetsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawAssetsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawAssetsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawAssetsClient + """ + return self._raw_client async def list( self, @@ -980,79 +444,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/assets", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "offset": offset, - "limit": limit, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Assets, - parse_obj_as( - type_=Assets, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.list(site_id, offset=offset, limit=limit, request_options=request_options) + return _response.data async def create( self, @@ -1120,84 +513,14 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/assets", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "fileName": file_name, - "fileHash": file_hash, - "parentFolder": parent_folder, - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.create( + site_id, + file_name=file_name, + file_hash=file_hash, + parent_folder=parent_folder, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AssetUpload, - parse_obj_as( - type_=AssetUpload, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Asset: """ @@ -1237,75 +560,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"assets/{jsonable_encoder(asset_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Asset, - parse_obj_as( - type_=Asset, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get(asset_id, request_options=request_options) + return _response.data async def delete(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ @@ -1344,69 +600,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"assets/{jsonable_encoder(asset_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.delete(asset_id, request_options=request_options) + return _response.data async def update( self, @@ -1459,83 +654,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"assets/{jsonable_encoder(asset_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "localeId": locale_id, - "displayName": display_name, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.update( + asset_id, locale_id=locale_id, display_name=display_name, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Asset, - parse_obj_as( - type_=Asset, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def list_folders( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -1577,75 +699,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/asset_folders", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AssetFolderList, - parse_obj_as( - type_=AssetFolderList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.list_folders(site_id, request_options=request_options) + return _response.data async def create_folder( self, @@ -1699,83 +754,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/asset_folders", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "displayName": display_name, - "parentFolder": parent_folder, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.create_folder( + site_id, display_name=display_name, parent_folder=parent_folder, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AssetFolder, - parse_obj_as( - type_=AssetFolder, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get_folder( self, asset_folder_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -1817,72 +799,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"asset_folders/{jsonable_encoder(asset_folder_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AssetFolder, - parse_obj_as( - type_=AssetFolder, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get_folder(asset_folder_id, request_options=request_options) + return _response.data diff --git a/src/webflow/resources/assets/raw_client.py b/src/webflow/resources/assets/raw_client.py new file mode 100644 index 0000000..5c99d98 --- /dev/null +++ b/src/webflow/resources/assets/raw_client.py @@ -0,0 +1,1805 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...errors.bad_request_error import BadRequestError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.asset import Asset +from ...types.asset_folder import AssetFolder +from ...types.asset_folder_list import AssetFolderList +from ...types.asset_upload import AssetUpload +from ...types.assets import Assets +from ...types.error import Error +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawAssetsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + site_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Assets]: + """ + List of assets uploaded to a site + + Required scope | `assets:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Assets] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Assets, + parse_obj_as( + type_=Assets, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create( + self, + site_id: str, + *, + file_name: str, + file_hash: str, + parent_folder: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[AssetUpload]: + """ + The first step in uploading an asset to a site. + + + This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. + + + Use these properties in the header of a [POST request to Amazson s3](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) to complete the upload. + + + To learn more about how to upload assets to Webflow, see our [assets guide](/data/docs/working-with-assets). + + Required scope | `assets:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_name : str + File name including file extension. File names must be less than 100 characters. + + file_hash : str + MD5 hash of the file + + parent_folder : typing.Optional[str] + ID of the Asset folder (optional) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[AssetUpload] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "fileName": file_name, + "fileHash": file_hash, + "parentFolder": parent_folder, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AssetUpload, + parse_obj_as( + type_=AssetUpload, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Asset]: + """ + Get details about an asset + + Required scope | `assets:read` + + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Asset] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Asset, + parse_obj_as( + type_=Asset, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete(self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[None]: + """ + Delete an Asset + + Required Scope: `assets: write` + + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update( + self, + asset_id: str, + *, + locale_id: typing.Optional[str] = OMIT, + display_name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Asset]: + """ + Update details of an Asset. + + Required scope | `assets:write` + + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + display_name : typing.Optional[str] + A human readable name for the asset + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Asset] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "localeId": locale_id, + "displayName": display_name, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Asset, + parse_obj_as( + type_=Asset, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def list_folders( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[AssetFolderList]: + """ + List Asset Folders within a given site + + Required scope | `assets:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[AssetFolderList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AssetFolderList, + parse_obj_as( + type_=AssetFolderList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create_folder( + self, + site_id: str, + *, + display_name: str, + parent_folder: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[AssetFolder]: + """ + Create an Asset Folder within a given site + + Required scope | `assets:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + display_name : str + A human readable name for the Asset Folder + + parent_folder : typing.Optional[str] + An (optional) pointer to a parent Asset Folder (or null for root) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[AssetFolder] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "displayName": display_name, + "parentFolder": parent_folder, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AssetFolder, + parse_obj_as( + type_=AssetFolder, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_folder( + self, asset_folder_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[AssetFolder]: + """ + Get details about a specific Asset Folder + + Required scope | `assets:read` + + Parameters + ---------- + asset_folder_id : str + Unique identifier for an Asset Folder + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[AssetFolder] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"asset_folders/{jsonable_encoder(asset_folder_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AssetFolder, + parse_obj_as( + type_=AssetFolder, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawAssetsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + site_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Assets]: + """ + List of assets uploaded to a site + + Required scope | `assets:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Assets] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Assets, + parse_obj_as( + type_=Assets, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create( + self, + site_id: str, + *, + file_name: str, + file_hash: str, + parent_folder: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[AssetUpload]: + """ + The first step in uploading an asset to a site. + + + This endpoint generates a response with the following information: `uploadUrl` and `uploadDetails`. + + + Use these properties in the header of a [POST request to Amazson s3](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) to complete the upload. + + + To learn more about how to upload assets to Webflow, see our [assets guide](/data/docs/working-with-assets). + + Required scope | `assets:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_name : str + File name including file extension. File names must be less than 100 characters. + + file_hash : str + MD5 hash of the file + + parent_folder : typing.Optional[str] + ID of the Asset folder (optional) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[AssetUpload] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/assets", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "fileName": file_name, + "fileHash": file_hash, + "parentFolder": parent_folder, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AssetUpload, + parse_obj_as( + type_=AssetUpload, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get( + self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Asset]: + """ + Get details about an asset + + Required scope | `assets:read` + + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Asset] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Asset, + parse_obj_as( + type_=Asset, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete( + self, asset_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Delete an Asset + + Required Scope: `assets: write` + + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update( + self, + asset_id: str, + *, + locale_id: typing.Optional[str] = OMIT, + display_name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Asset]: + """ + Update details of an Asset. + + Required scope | `assets:write` + + Parameters + ---------- + asset_id : str + Unique identifier for an Asset on a site + + locale_id : typing.Optional[str] + Unique identifier for a specific locale. Applicable, when using localization. + + display_name : typing.Optional[str] + A human readable name for the asset + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Asset] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"assets/{jsonable_encoder(asset_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "localeId": locale_id, + "displayName": display_name, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Asset, + parse_obj_as( + type_=Asset, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def list_folders( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[AssetFolderList]: + """ + List Asset Folders within a given site + + Required scope | `assets:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[AssetFolderList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AssetFolderList, + parse_obj_as( + type_=AssetFolderList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create_folder( + self, + site_id: str, + *, + display_name: str, + parent_folder: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[AssetFolder]: + """ + Create an Asset Folder within a given site + + Required scope | `assets:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + display_name : str + A human readable name for the Asset Folder + + parent_folder : typing.Optional[str] + An (optional) pointer to a parent Asset Folder (or null for root) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[AssetFolder] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/asset_folders", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "displayName": display_name, + "parentFolder": parent_folder, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AssetFolder, + parse_obj_as( + type_=AssetFolder, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_folder( + self, asset_folder_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[AssetFolder]: + """ + Get details about a specific Asset Folder + + Required scope | `assets:read` + + Parameters + ---------- + asset_folder_id : str + Unique identifier for an Asset Folder + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[AssetFolder] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"asset_folders/{jsonable_encoder(asset_folder_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AssetFolder, + parse_obj_as( + type_=AssetFolder, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/collections/__init__.py b/src/webflow/resources/collections/__init__.py index 3796806..07eb5d1 100644 --- a/src/webflow/resources/collections/__init__.py +++ b/src/webflow/resources/collections/__init__.py @@ -1,32 +1,83 @@ # This file was auto-generated by Fern from our API Definition. -from .resources import ( - CreateBulkCollectionItemRequestBodyFieldData, - CreateBulkCollectionItemRequestBodyFieldDataItem, - ItemIDs, - ItemIDsWithLocales, - ItemsCreateItemLiveRequestBody, - ItemsCreateItemRequestBody, - ItemsDeleteItemsLiveRequestItemsItem, - ItemsDeleteItemsRequestItemsItem, - ItemsListItemsLiveRequestSortBy, - ItemsListItemsLiveRequestSortOrder, - ItemsListItemsRequestSortBy, - ItemsListItemsRequestSortOrder, - ItemsPublishItemRequest, - ItemsPublishItemRequestItemsItemsItem, - ItemsPublishItemResponse, - ItemsUpdateItemsResponse, - MultipleItems, - MultipleLiveItems, - SingleCmsItem, - fields, - items, -) +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .resources import ( + CreateBulkCollectionItemRequestBodyFieldData, + CreateBulkCollectionItemRequestBodyFieldDataOneItem, + ItemIDs, + ItemIDsWithLocales, + ItemsCreateItemLiveRequestBody, + ItemsCreateItemRequestBody, + ItemsDeleteItemsLiveRequestItemsItem, + ItemsDeleteItemsRequestItemsItem, + ItemsListItemsLiveRequestSortBy, + ItemsListItemsLiveRequestSortOrder, + ItemsListItemsRequestSortBy, + ItemsListItemsRequestSortOrder, + ItemsPublishItemRequest, + ItemsPublishItemRequestItemsItemsItem, + ItemsPublishItemResponse, + ItemsUpdateItemsResponse, + MultipleItems, + MultipleLiveItems, + SingleCmsItem, + fields, + items, + ) +_dynamic_imports: typing.Dict[str, str] = { + "CreateBulkCollectionItemRequestBodyFieldData": ".resources", + "CreateBulkCollectionItemRequestBodyFieldDataOneItem": ".resources", + "ItemIDs": ".resources", + "ItemIDsWithLocales": ".resources", + "ItemsCreateItemLiveRequestBody": ".resources", + "ItemsCreateItemRequestBody": ".resources", + "ItemsDeleteItemsLiveRequestItemsItem": ".resources", + "ItemsDeleteItemsRequestItemsItem": ".resources", + "ItemsListItemsLiveRequestSortBy": ".resources", + "ItemsListItemsLiveRequestSortOrder": ".resources", + "ItemsListItemsRequestSortBy": ".resources", + "ItemsListItemsRequestSortOrder": ".resources", + "ItemsPublishItemRequest": ".resources", + "ItemsPublishItemRequestItemsItemsItem": ".resources", + "ItemsPublishItemResponse": ".resources", + "ItemsUpdateItemsResponse": ".resources", + "MultipleItems": ".resources", + "MultipleLiveItems": ".resources", + "SingleCmsItem": ".resources", + "fields": ".resources", + "items": ".resources", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", - "CreateBulkCollectionItemRequestBodyFieldDataItem", + "CreateBulkCollectionItemRequestBodyFieldDataOneItem", "ItemIDs", "ItemIDsWithLocales", "ItemsCreateItemLiveRequestBody", diff --git a/src/webflow/resources/collections/client.py b/src/webflow/resources/collections/client.py index 61495ae..bd4adca 100644 --- a/src/webflow/resources/collections/client.py +++ b/src/webflow/resources/collections/client.py @@ -1,38 +1,40 @@ # This file was auto-generated by Fern from our API Definition. +from __future__ import annotations + import typing -from ...core.client_wrapper import SyncClientWrapper -from .resources.fields.client import FieldsClient -from .resources.items.client import ItemsClient + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.collection import Collection from ...types.collection_list import CollectionList -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.not_found_error import NotFoundError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError from ...types.field_create import FieldCreate -from ...types.collection import Collection -from ...core.serialization import convert_and_respect_annotation_metadata -from ...errors.conflict_error import ConflictError -from ...core.client_wrapper import AsyncClientWrapper -from .resources.fields.client import AsyncFieldsClient -from .resources.items.client import AsyncItemsClient +from .raw_client import AsyncRawCollectionsClient, RawCollectionsClient +if typing.TYPE_CHECKING: + from .resources.fields.client import AsyncFieldsClient, FieldsClient + from .resources.items.client import AsyncItemsClient, ItemsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) class CollectionsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawCollectionsClient(client_wrapper=client_wrapper) self._client_wrapper = client_wrapper - self.fields = FieldsClient(client_wrapper=self._client_wrapper) - self.items = ItemsClient(client_wrapper=self._client_wrapper) + self._fields: typing.Optional[FieldsClient] = None + self._items: typing.Optional[ItemsClient] = None + + @property + def with_raw_response(self) -> RawCollectionsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawCollectionsClient + """ + return self._raw_client def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> CollectionList: """ @@ -64,75 +66,8 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/collections", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionList, - parse_obj_as( - type_=CollectionList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.list(site_id, request_options=request_options) + return _response.data def create( self, @@ -213,97 +148,15 @@ def create( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/collections", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "displayName": display_name, - "singularName": singular_name, - "slug": slug, - "fields": convert_and_respect_annotation_metadata( - object_=fields, annotation=typing.Sequence[FieldCreate], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.create( + site_id, + display_name=display_name, + singular_name=singular_name, + slug=slug, + fields=fields, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Collection, - parse_obj_as( - type_=Collection, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get(self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Collection: """ @@ -335,75 +188,8 @@ def get(self, collection_id: str, *, request_options: typing.Optional[RequestOpt collection_id="580e63fc8c9a982ac9b8b745", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Collection, - parse_obj_as( - type_=Collection, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get(collection_id, request_options=request_options) + return _response.data def delete(self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ @@ -434,76 +220,43 @@ def delete(self, collection_id: str, *, request_options: typing.Optional[Request collection_id="580e63fc8c9a982ac9b8b745", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete(collection_id, request_options=request_options) + return _response.data + + @property + def fields(self): + if self._fields is None: + from .resources.fields.client import FieldsClient # noqa: E402 + + self._fields = FieldsClient(client_wrapper=self._client_wrapper) + return self._fields + + @property + def items(self): + if self._items is None: + from .resources.items.client import ItemsClient # noqa: E402 + + self._items = ItemsClient(client_wrapper=self._client_wrapper) + return self._items class AsyncCollectionsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawCollectionsClient(client_wrapper=client_wrapper) self._client_wrapper = client_wrapper - self.fields = AsyncFieldsClient(client_wrapper=self._client_wrapper) - self.items = AsyncItemsClient(client_wrapper=self._client_wrapper) + self._fields: typing.Optional[AsyncFieldsClient] = None + self._items: typing.Optional[AsyncItemsClient] = None + + @property + def with_raw_response(self) -> AsyncRawCollectionsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawCollectionsClient + """ + return self._raw_client async def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> CollectionList: """ @@ -543,75 +296,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/collections", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionList, - parse_obj_as( - type_=CollectionList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.list(site_id, request_options=request_options) + return _response.data async def create( self, @@ -705,97 +391,15 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/collections", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "displayName": display_name, - "singularName": singular_name, - "slug": slug, - "fields": convert_and_respect_annotation_metadata( - object_=fields, annotation=typing.Sequence[FieldCreate], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.create( + site_id, + display_name=display_name, + singular_name=singular_name, + slug=slug, + fields=fields, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Collection, - parse_obj_as( - type_=Collection, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get(self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Collection: """ @@ -835,75 +439,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Collection, - parse_obj_as( - type_=Collection, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get(collection_id, request_options=request_options) + return _response.data async def delete(self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ @@ -942,66 +479,21 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.delete(collection_id, request_options=request_options) + return _response.data + + @property + def fields(self): + if self._fields is None: + from .resources.fields.client import AsyncFieldsClient # noqa: E402 + + self._fields = AsyncFieldsClient(client_wrapper=self._client_wrapper) + return self._fields + + @property + def items(self): + if self._items is None: + from .resources.items.client import AsyncItemsClient # noqa: E402 + + self._items = AsyncItemsClient(client_wrapper=self._client_wrapper) + return self._items diff --git a/src/webflow/resources/collections/raw_client.py b/src/webflow/resources/collections/raw_client.py new file mode 100644 index 0000000..ffc8451 --- /dev/null +++ b/src/webflow/resources/collections/raw_client.py @@ -0,0 +1,917 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...core.serialization import convert_and_respect_annotation_metadata +from ...errors.bad_request_error import BadRequestError +from ...errors.conflict_error import ConflictError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.collection import Collection +from ...types.collection_list import CollectionList +from ...types.error import Error +from ...types.field_create import FieldCreate +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawCollectionsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[CollectionList]: + """ + List of all Collections within a Site. + + Required scope | `cms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CollectionList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionList, + parse_obj_as( + type_=CollectionList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create( + self, + site_id: str, + *, + display_name: str, + singular_name: str, + slug: typing.Optional[str] = OMIT, + fields: typing.Optional[typing.Sequence[FieldCreate]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Collection]: + """ + Create a Collection for a site with collection fields. + + Each collection includes the required _name_ and _slug_ fields, which are generated automatically. You can update the `displayName` of these fields, but the slug for them cannot be changed. Fields slugs are automatically converted to lowercase. Spaces in slugs are replaced with hyphens. + + Required scope | `cms:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + display_name : str + Name of the collection. Each collection name must be distinct. + + singular_name : str + Singular name of each item. + + slug : typing.Optional[str] + Part of a URL that identifier + + fields : typing.Optional[typing.Sequence[FieldCreate]] + An array of custom fields to add to the collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Collection] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "displayName": display_name, + "singularName": singular_name, + "slug": slug, + "fields": convert_and_respect_annotation_metadata( + object_=fields, annotation=typing.Sequence[FieldCreate], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Collection, + parse_obj_as( + type_=Collection, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get( + self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[Collection]: + """ + Get the full details of a collection from its ID. + + Required scope | `cms:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Collection] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Collection, + parse_obj_as( + type_=Collection, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete( + self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + Delete a collection using its ID. + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawCollectionsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[CollectionList]: + """ + List of all Collections within a Site. + + Required scope | `cms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CollectionList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionList, + parse_obj_as( + type_=CollectionList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create( + self, + site_id: str, + *, + display_name: str, + singular_name: str, + slug: typing.Optional[str] = OMIT, + fields: typing.Optional[typing.Sequence[FieldCreate]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Collection]: + """ + Create a Collection for a site with collection fields. + + Each collection includes the required _name_ and _slug_ fields, which are generated automatically. You can update the `displayName` of these fields, but the slug for them cannot be changed. Fields slugs are automatically converted to lowercase. Spaces in slugs are replaced with hyphens. + + Required scope | `cms:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + display_name : str + Name of the collection. Each collection name must be distinct. + + singular_name : str + Singular name of each item. + + slug : typing.Optional[str] + Part of a URL that identifier + + fields : typing.Optional[typing.Sequence[FieldCreate]] + An array of custom fields to add to the collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Collection] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/collections", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "displayName": display_name, + "singularName": singular_name, + "slug": slug, + "fields": convert_and_respect_annotation_metadata( + object_=fields, annotation=typing.Sequence[FieldCreate], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Collection, + parse_obj_as( + type_=Collection, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get( + self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Collection]: + """ + Get the full details of a collection from its ID. + + Required scope | `cms:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Collection] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Collection, + parse_obj_as( + type_=Collection, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete( + self, collection_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Delete a collection using its ID. + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/collections/resources/__init__.py b/src/webflow/resources/collections/resources/__init__.py index 4ad4d58..7123bf3 100644 --- a/src/webflow/resources/collections/resources/__init__.py +++ b/src/webflow/resources/collections/resources/__init__.py @@ -1,31 +1,82 @@ # This file was auto-generated by Fern from our API Definition. -from . import fields, items -from .items import ( - CreateBulkCollectionItemRequestBodyFieldData, - CreateBulkCollectionItemRequestBodyFieldDataItem, - ItemIDs, - ItemIDsWithLocales, - ItemsCreateItemLiveRequestBody, - ItemsCreateItemRequestBody, - ItemsDeleteItemsLiveRequestItemsItem, - ItemsDeleteItemsRequestItemsItem, - ItemsListItemsLiveRequestSortBy, - ItemsListItemsLiveRequestSortOrder, - ItemsListItemsRequestSortBy, - ItemsListItemsRequestSortOrder, - ItemsPublishItemRequest, - ItemsPublishItemRequestItemsItemsItem, - ItemsPublishItemResponse, - ItemsUpdateItemsResponse, - MultipleItems, - MultipleLiveItems, - SingleCmsItem, -) +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from . import fields, items + from .items import ( + CreateBulkCollectionItemRequestBodyFieldData, + CreateBulkCollectionItemRequestBodyFieldDataOneItem, + ItemIDs, + ItemIDsWithLocales, + ItemsCreateItemLiveRequestBody, + ItemsCreateItemRequestBody, + ItemsDeleteItemsLiveRequestItemsItem, + ItemsDeleteItemsRequestItemsItem, + ItemsListItemsLiveRequestSortBy, + ItemsListItemsLiveRequestSortOrder, + ItemsListItemsRequestSortBy, + ItemsListItemsRequestSortOrder, + ItemsPublishItemRequest, + ItemsPublishItemRequestItemsItemsItem, + ItemsPublishItemResponse, + ItemsUpdateItemsResponse, + MultipleItems, + MultipleLiveItems, + SingleCmsItem, + ) +_dynamic_imports: typing.Dict[str, str] = { + "CreateBulkCollectionItemRequestBodyFieldData": ".items", + "CreateBulkCollectionItemRequestBodyFieldDataOneItem": ".items", + "ItemIDs": ".items", + "ItemIDsWithLocales": ".items", + "ItemsCreateItemLiveRequestBody": ".items", + "ItemsCreateItemRequestBody": ".items", + "ItemsDeleteItemsLiveRequestItemsItem": ".items", + "ItemsDeleteItemsRequestItemsItem": ".items", + "ItemsListItemsLiveRequestSortBy": ".items", + "ItemsListItemsLiveRequestSortOrder": ".items", + "ItemsListItemsRequestSortBy": ".items", + "ItemsListItemsRequestSortOrder": ".items", + "ItemsPublishItemRequest": ".items", + "ItemsPublishItemRequestItemsItemsItem": ".items", + "ItemsPublishItemResponse": ".items", + "ItemsUpdateItemsResponse": ".items", + "MultipleItems": ".items", + "MultipleLiveItems": ".items", + "SingleCmsItem": ".items", + "fields": ".fields", + "items": ".items", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", - "CreateBulkCollectionItemRequestBodyFieldDataItem", + "CreateBulkCollectionItemRequestBodyFieldDataOneItem", "ItemIDs", "ItemIDsWithLocales", "ItemsCreateItemLiveRequestBody", diff --git a/src/webflow/resources/collections/resources/fields/__init__.py b/src/webflow/resources/collections/resources/fields/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/collections/resources/fields/__init__.py +++ b/src/webflow/resources/collections/resources/fields/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/collections/resources/fields/client.py b/src/webflow/resources/collections/resources/fields/client.py index c2b7ebc..b4f337b 100644 --- a/src/webflow/resources/collections/resources/fields/client.py +++ b/src/webflow/resources/collections/resources/fields/client.py @@ -1,23 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -from .....core.client_wrapper import SyncClientWrapper -from .....types.field_create import FieldCreate + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions -from .....core.jsonable_encoder import jsonable_encoder -from .....core.serialization import convert_and_respect_annotation_metadata -from .....core.pydantic_utilities import parse_obj_as -from .....errors.bad_request_error import BadRequestError -from .....errors.unauthorized_error import UnauthorizedError -from .....types.error import Error -from .....errors.not_found_error import NotFoundError -from .....errors.conflict_error import ConflictError -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError from .....types.field import Field -from .....core.client_wrapper import AsyncClientWrapper +from .....types.field_create import FieldCreate +from .raw_client import AsyncRawFieldsClient, RawFieldsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -25,7 +14,18 @@ class FieldsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawFieldsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawFieldsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawFieldsClient + """ + return self._raw_client def create( self, collection_id: str, *, request: FieldCreate, request_options: typing.Optional[RequestOptions] = None @@ -73,87 +73,8 @@ def create( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/fields", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json=convert_and_respect_annotation_metadata(object_=request, annotation=FieldCreate, direction="write"), - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FieldCreate, - parse_obj_as( - type_=FieldCreate, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.create(collection_id, request=request, request_options=request_options) + return _response.data def delete( self, collection_id: str, field_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -190,69 +111,8 @@ def delete( field_id="580e63fc8c9a982ac9b8b745", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete(collection_id, field_id, request_options=request_options) + return _response.data def update( self, @@ -309,89 +169,31 @@ def update( help_text="Add the body of your post here", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "isRequired": is_required, - "displayName": display_name, - "helpText": help_text, - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.update( + collection_id, + field_id, + is_required=is_required, + display_name=display_name, + help_text=help_text, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Field, - parse_obj_as( - type_=Field, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data class AsyncFieldsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawFieldsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawFieldsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawFieldsClient + """ + return self._raw_client async def create( self, collection_id: str, *, request: FieldCreate, request_options: typing.Optional[RequestOptions] = None @@ -447,87 +249,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/fields", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json=convert_and_respect_annotation_metadata(object_=request, annotation=FieldCreate, direction="write"), - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FieldCreate, - parse_obj_as( - type_=FieldCreate, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.create(collection_id, request=request, request_options=request_options) + return _response.data async def delete( self, collection_id: str, field_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -572,69 +295,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.delete(collection_id, field_id, request_options=request_options) + return _response.data async def update( self, @@ -699,81 +361,12 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "isRequired": is_required, - "displayName": display_name, - "helpText": help_text, - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.update( + collection_id, + field_id, + is_required=is_required, + display_name=display_name, + help_text=help_text, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Field, - parse_obj_as( - type_=Field, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data diff --git a/src/webflow/resources/collections/resources/fields/raw_client.py b/src/webflow/resources/collections/resources/fields/raw_client.py new file mode 100644 index 0000000..31f26be --- /dev/null +++ b/src/webflow/resources/collections/resources/fields/raw_client.py @@ -0,0 +1,732 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....core.serialization import convert_and_respect_annotation_metadata +from .....errors.bad_request_error import BadRequestError +from .....errors.conflict_error import ConflictError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....types.field import Field +from .....types.field_create import FieldCreate +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawFieldsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def create( + self, collection_id: str, *, request: FieldCreate, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[FieldCreate]: + """ + Create a custom field in a collection. + + Field validation is currently not available through the API. + + Bulk creation of fields is not supported with this endpoint. To add multiple fields at once, include them when you [create the collection.](/data/v2.0.0/reference/cms/collections/create) + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request : FieldCreate + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[FieldCreate] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/fields", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json=convert_and_respect_annotation_metadata(object_=request, annotation=FieldCreate, direction="write"), + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FieldCreate, + parse_obj_as( + type_=FieldCreate, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete( + self, collection_id: str, field_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + Delete a custom field in a collection. This endpoint does not currently support bulk deletion. + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_id : str + Unique identifier for a Field in a collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update( + self, + collection_id: str, + field_id: str, + *, + is_required: typing.Optional[bool] = OMIT, + display_name: typing.Optional[str] = OMIT, + help_text: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Field]: + """ + Update a custom field in a collection. + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_id : str + Unique identifier for a Field in a collection + + is_required : typing.Optional[bool] + Define whether a field is required in a collection + + display_name : typing.Optional[str] + The name of a field + + help_text : typing.Optional[str] + Additional text to help anyone filling out this field + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Field] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "isRequired": is_required, + "displayName": display_name, + "helpText": help_text, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Field, + parse_obj_as( + type_=Field, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawFieldsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def create( + self, collection_id: str, *, request: FieldCreate, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[FieldCreate]: + """ + Create a custom field in a collection. + + Field validation is currently not available through the API. + + Bulk creation of fields is not supported with this endpoint. To add multiple fields at once, include them when you [create the collection.](/data/v2.0.0/reference/cms/collections/create) + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request : FieldCreate + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[FieldCreate] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/fields", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json=convert_and_respect_annotation_metadata(object_=request, annotation=FieldCreate, direction="write"), + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FieldCreate, + parse_obj_as( + type_=FieldCreate, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete( + self, collection_id: str, field_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Delete a custom field in a collection. This endpoint does not currently support bulk deletion. + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_id : str + Unique identifier for a Field in a collection + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update( + self, + collection_id: str, + field_id: str, + *, + is_required: typing.Optional[bool] = OMIT, + display_name: typing.Optional[str] = OMIT, + help_text: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Field]: + """ + Update a custom field in a collection. + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_id : str + Unique identifier for a Field in a collection + + is_required : typing.Optional[bool] + Define whether a field is required in a collection + + display_name : typing.Optional[str] + The name of a field + + help_text : typing.Optional[str] + Additional text to help anyone filling out this field + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Field] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/fields/{jsonable_encoder(field_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "isRequired": is_required, + "displayName": display_name, + "helpText": help_text, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Field, + parse_obj_as( + type_=Field, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/collections/resources/items/__init__.py b/src/webflow/resources/collections/resources/items/__init__.py index 7dce40c..ae89439 100644 --- a/src/webflow/resources/collections/resources/items/__init__.py +++ b/src/webflow/resources/collections/resources/items/__init__.py @@ -1,30 +1,79 @@ # This file was auto-generated by Fern from our API Definition. -from .types import ( - CreateBulkCollectionItemRequestBodyFieldData, - CreateBulkCollectionItemRequestBodyFieldDataItem, - ItemIDs, - ItemIDsWithLocales, - ItemsCreateItemLiveRequestBody, - ItemsCreateItemRequestBody, - ItemsDeleteItemsLiveRequestItemsItem, - ItemsDeleteItemsRequestItemsItem, - ItemsListItemsLiveRequestSortBy, - ItemsListItemsLiveRequestSortOrder, - ItemsListItemsRequestSortBy, - ItemsListItemsRequestSortOrder, - ItemsPublishItemRequest, - ItemsPublishItemRequestItemsItemsItem, - ItemsPublishItemResponse, - ItemsUpdateItemsResponse, - MultipleItems, - MultipleLiveItems, - SingleCmsItem, -) +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import ( + CreateBulkCollectionItemRequestBodyFieldData, + CreateBulkCollectionItemRequestBodyFieldDataOneItem, + ItemIDs, + ItemIDsWithLocales, + ItemsCreateItemLiveRequestBody, + ItemsCreateItemRequestBody, + ItemsDeleteItemsLiveRequestItemsItem, + ItemsDeleteItemsRequestItemsItem, + ItemsListItemsLiveRequestSortBy, + ItemsListItemsLiveRequestSortOrder, + ItemsListItemsRequestSortBy, + ItemsListItemsRequestSortOrder, + ItemsPublishItemRequest, + ItemsPublishItemRequestItemsItemsItem, + ItemsPublishItemResponse, + ItemsUpdateItemsResponse, + MultipleItems, + MultipleLiveItems, + SingleCmsItem, + ) +_dynamic_imports: typing.Dict[str, str] = { + "CreateBulkCollectionItemRequestBodyFieldData": ".types", + "CreateBulkCollectionItemRequestBodyFieldDataOneItem": ".types", + "ItemIDs": ".types", + "ItemIDsWithLocales": ".types", + "ItemsCreateItemLiveRequestBody": ".types", + "ItemsCreateItemRequestBody": ".types", + "ItemsDeleteItemsLiveRequestItemsItem": ".types", + "ItemsDeleteItemsRequestItemsItem": ".types", + "ItemsListItemsLiveRequestSortBy": ".types", + "ItemsListItemsLiveRequestSortOrder": ".types", + "ItemsListItemsRequestSortBy": ".types", + "ItemsListItemsRequestSortOrder": ".types", + "ItemsPublishItemRequest": ".types", + "ItemsPublishItemRequestItemsItemsItem": ".types", + "ItemsPublishItemResponse": ".types", + "ItemsUpdateItemsResponse": ".types", + "MultipleItems": ".types", + "MultipleLiveItems": ".types", + "SingleCmsItem": ".types", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", - "CreateBulkCollectionItemRequestBodyFieldDataItem", + "CreateBulkCollectionItemRequestBodyFieldDataOneItem", "ItemIDs", "ItemIDsWithLocales", "ItemsCreateItemLiveRequestBody", diff --git a/src/webflow/resources/collections/resources/items/client.py b/src/webflow/resources/collections/resources/items/client.py index 0e04307..16f1d5c 100644 --- a/src/webflow/resources/collections/resources/items/client.py +++ b/src/webflow/resources/collections/resources/items/client.py @@ -1,41 +1,30 @@ # This file was auto-generated by Fern from our API Definition. import typing -from .....core.client_wrapper import SyncClientWrapper -from .....types.items_list_items_request_last_published import ItemsListItemsRequestLastPublished -from .types.items_list_items_request_sort_by import ItemsListItemsRequestSortBy -from .types.items_list_items_request_sort_order import ItemsListItemsRequestSortOrder + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions -from .....types.collection_item_list import CollectionItemList -from .....core.jsonable_encoder import jsonable_encoder -from .....core.serialization import convert_and_respect_annotation_metadata -from .....core.pydantic_utilities import parse_obj_as -from .....errors.bad_request_error import BadRequestError -from .....errors.unauthorized_error import UnauthorizedError -from .....types.error import Error -from .....errors.not_found_error import NotFoundError -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError -from .types.items_create_item_request_body import ItemsCreateItemRequestBody +from .....types.bulk_collection_item import BulkCollectionItem from .....types.collection_item import CollectionItem -from .types.items_delete_items_request_items_item import ItemsDeleteItemsRequestItemsItem -from .....errors.conflict_error import ConflictError +from .....types.collection_item_list import CollectionItemList +from .....types.collection_item_list_no_pagination import CollectionItemListNoPagination +from .....types.collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData from .....types.collection_item_with_id_input import CollectionItemWithIdInput -from .types.items_update_items_response import ItemsUpdateItemsResponse from .....types.items_list_items_live_request_last_published import ItemsListItemsLiveRequestLastPublished -from .types.items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy -from .types.items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder +from .....types.items_list_items_request_last_published import ItemsListItemsRequestLastPublished +from .raw_client import AsyncRawItemsClient, RawItemsClient +from .types.create_bulk_collection_item_request_body_field_data import CreateBulkCollectionItemRequestBodyFieldData from .types.items_create_item_live_request_body import ItemsCreateItemLiveRequestBody +from .types.items_create_item_request_body import ItemsCreateItemRequestBody from .types.items_delete_items_live_request_items_item import ItemsDeleteItemsLiveRequestItemsItem -from .....types.collection_item_list_no_pagination import CollectionItemListNoPagination -from .types.create_bulk_collection_item_request_body_field_data import CreateBulkCollectionItemRequestBodyFieldData -from .....types.bulk_collection_item import BulkCollectionItem -from .....types.collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData +from .types.items_delete_items_request_items_item import ItemsDeleteItemsRequestItemsItem +from .types.items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy +from .types.items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder +from .types.items_list_items_request_sort_by import ItemsListItemsRequestSortBy +from .types.items_list_items_request_sort_order import ItemsListItemsRequestSortOrder from .types.items_publish_item_request import ItemsPublishItemRequest from .types.items_publish_item_response import ItemsPublishItemResponse -from .....core.client_wrapper import AsyncClientWrapper +from .types.items_update_items_response import ItemsUpdateItemsResponse # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -43,7 +32,18 @@ class ItemsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawItemsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawItemsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawItemsClient + """ + return self._raw_client def list_items( self, @@ -119,87 +119,19 @@ def list_items( sort_order="asc", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "cmsLocaleId": cms_locale_id, - "offset": offset, - "limit": limit, - "name": name, - "slug": slug, - "lastPublished": convert_and_respect_annotation_metadata( - object_=last_published, annotation=ItemsListItemsRequestLastPublished, direction="write" - ), - "sortBy": sort_by, - "sortOrder": sort_order, - }, + _response = self._raw_client.list_items( + collection_id, + cms_locale_id=cms_locale_id, + offset=offset, + limit=limit, + name=name, + slug=slug, + last_published=last_published, + sort_by=sort_by, + sort_order=sort_order, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItemList, - parse_obj_as( - type_=CollectionItemList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def create_item( self, @@ -259,82 +191,10 @@ def create_item( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemRequestBody, direction="write" - ), - request_options=request_options, - omit=OMIT, + _response = self._raw_client.create_item( + collection_id, request=request, skip_invalid_files=skip_invalid_files, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def delete_items( self, @@ -383,88 +243,8 @@ def delete_items( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - json={ - "items": convert_and_respect_annotation_metadata( - object_=items, annotation=typing.Sequence[ItemsDeleteItemsRequestItemsItem], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete_items(collection_id, items=items, request_options=request_options) + return _response.data def update_items( self, @@ -551,87 +331,10 @@ def update_items( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json={ - "items": convert_and_respect_annotation_metadata( - object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.update_items( + collection_id, skip_invalid_files=skip_invalid_files, items=items, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ItemsUpdateItemsResponse, - parse_obj_as( - type_=ItemsUpdateItemsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def list_items_live( self, @@ -711,87 +414,19 @@ def list_items_live( sort_order="asc", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/live", - base_url=self._client_wrapper.get_environment().data_api, - method="GET", - params={ - "cmsLocaleId": cms_locale_id, - "offset": offset, - "limit": limit, - "name": name, - "slug": slug, - "lastPublished": convert_and_respect_annotation_metadata( - object_=last_published, annotation=ItemsListItemsLiveRequestLastPublished, direction="write" - ), - "sortBy": sort_by, - "sortOrder": sort_order, - }, + _response = self._raw_client.list_items_live( + collection_id, + cms_locale_id=cms_locale_id, + offset=offset, + limit=limit, + name=name, + slug=slug, + last_published=last_published, + sort_by=sort_by, + sort_order=sort_order, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItemList, - parse_obj_as( - type_=CollectionItemList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def create_item_live( self, @@ -848,82 +483,10 @@ def create_item_live( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/live", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemLiveRequestBody, direction="write" - ), - request_options=request_options, - omit=OMIT, + _response = self._raw_client.create_item_live( + collection_id, request=request, skip_invalid_files=skip_invalid_files, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def delete_items_live( self, @@ -972,78 +535,8 @@ def delete_items_live( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/live", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - json={ - "items": convert_and_respect_annotation_metadata( - object_=items, annotation=typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete_items_live(collection_id, items=items, request_options=request_options) + return _response.data def update_items_live( self, @@ -1128,97 +621,10 @@ def update_items_live( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/live", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json={ - "items": convert_and_respect_annotation_metadata( - object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.update_items_live( + collection_id, skip_invalid_files=skip_invalid_files, items=items, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItemListNoPagination, - parse_obj_as( - type_=CollectionItemListNoPagination, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def create_items( self, @@ -1292,90 +698,16 @@ def create_items( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/bulk", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json={ - "cmsLocaleIds": cms_locale_ids, - "isArchived": is_archived, - "isDraft": is_draft, - "fieldData": convert_and_respect_annotation_metadata( - object_=field_data, annotation=CreateBulkCollectionItemRequestBodyFieldData, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.create_items( + collection_id, + field_data=field_data, + skip_invalid_files=skip_invalid_files, + cms_locale_ids=cms_locale_ids, + is_archived=is_archived, + is_draft=is_draft, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - BulkCollectionItem, - parse_obj_as( - type_=BulkCollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get_item( self, @@ -1422,78 +754,10 @@ def get_item( cms_locale_id="cmsLocaleId", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "cmsLocaleId": cms_locale_id, - }, - request_options=request_options, + _response = self._raw_client.get_item( + collection_id, item_id, cms_locale_id=cms_locale_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def delete_item( self, @@ -1539,72 +803,10 @@ def delete_item( cms_locale_id="cmsLocaleId", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - params={ - "cmsLocaleId": cms_locale_id, - }, - request_options=request_options, + _response = self._raw_client.delete_item( + collection_id, item_id, cms_locale_id=cms_locale_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def update_item( self, @@ -1688,91 +890,21 @@ def update_item( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json={ - "id": id, - "cmsLocaleId": cms_locale_id, - "lastPublished": last_published, - "lastUpdated": last_updated, - "createdOn": created_on, - "isArchived": is_archived, - "isDraft": is_draft, - "fieldData": convert_and_respect_annotation_metadata( - object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" - ), - }, + _response = self._raw_client.update_item( + collection_id, + item_id, + skip_invalid_files=skip_invalid_files, + id=id, + cms_locale_id=cms_locale_id, + last_published=last_published, + last_updated=last_updated, + created_on=created_on, + is_archived=is_archived, + is_draft=is_draft, + field_data=field_data, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get_item_live( self, @@ -1823,78 +955,10 @@ def get_item_live( cms_locale_id="cmsLocaleId", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", - base_url=self._client_wrapper.get_environment().data_api, - method="GET", - params={ - "cmsLocaleId": cms_locale_id, - }, - request_options=request_options, + _response = self._raw_client.get_item_live( + collection_id, item_id, cms_locale_id=cms_locale_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def delete_item_live( self, @@ -1942,72 +1006,10 @@ def delete_item_live( cms_locale_id="cmsLocaleId", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - params={ - "cmsLocaleId": cms_locale_id, - }, - request_options=request_options, + _response = self._raw_client.delete_item_live( + collection_id, item_id, cms_locale_id=cms_locale_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def update_item_live( self, @@ -2091,101 +1093,21 @@ def update_item_live( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json={ - "id": id, - "cmsLocaleId": cms_locale_id, - "lastPublished": last_published, - "lastUpdated": last_updated, - "createdOn": created_on, - "isArchived": is_archived, - "isDraft": is_draft, - "fieldData": convert_and_respect_annotation_metadata( - object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" - ), - }, + _response = self._raw_client.update_item_live( + collection_id, + item_id, + skip_invalid_files=skip_invalid_files, + id=id, + cms_locale_id=cms_locale_id, + last_published=last_published, + last_updated=last_updated, + created_on=created_on, + is_archived=is_archived, + is_draft=is_draft, + field_data=field_data, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def publish_item( self, @@ -2233,94 +1155,24 @@ def publish_item( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/publish", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsPublishItemRequest, direction="write" - ), - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ItemsPublishItemResponse, - parse_obj_as( - type_=ItemsPublishItemResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.publish_item(collection_id, request=request, request_options=request_options) + return _response.data class AsyncItemsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawItemsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawItemsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawItemsClient + """ + return self._raw_client async def list_items( self, @@ -2404,87 +1256,19 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "cmsLocaleId": cms_locale_id, - "offset": offset, - "limit": limit, - "name": name, - "slug": slug, - "lastPublished": convert_and_respect_annotation_metadata( - object_=last_published, annotation=ItemsListItemsRequestLastPublished, direction="write" - ), - "sortBy": sort_by, - "sortOrder": sort_order, - }, + _response = await self._raw_client.list_items( + collection_id, + cms_locale_id=cms_locale_id, + offset=offset, + limit=limit, + name=name, + slug=slug, + last_published=last_published, + sort_by=sort_by, + sort_order=sort_order, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItemList, - parse_obj_as( - type_=CollectionItemList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def create_item( self, @@ -2552,82 +1336,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemRequestBody, direction="write" - ), - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.create_item( + collection_id, request=request, skip_invalid_files=skip_invalid_files, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def delete_items( self, @@ -2671,101 +1383,21 @@ async def delete_items( ) - async def main() -> None: - await client.collections.items.delete_items( - collection_id="580e63fc8c9a982ac9b8b745", - items=[ - ItemsDeleteItemsRequestItemsItem( - id="580e64008c9a982ac9b8b754", - ) - ], - ) - - - asyncio.run(main()) - """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - json={ - "items": convert_and_respect_annotation_metadata( - object_=items, annotation=typing.Sequence[ItemsDeleteItemsRequestItemsItem], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), + async def main() -> None: + await client.collections.items.delete_items( + collection_id="580e63fc8c9a982ac9b8b745", + items=[ + ItemsDeleteItemsRequestItemsItem( + id="580e64008c9a982ac9b8b754", ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + ], + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.delete_items(collection_id, items=items, request_options=request_options) + return _response.data async def update_items( self, @@ -2860,87 +1492,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json={ - "items": convert_and_respect_annotation_metadata( - object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.update_items( + collection_id, skip_invalid_files=skip_invalid_files, items=items, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ItemsUpdateItemsResponse, - parse_obj_as( - type_=ItemsUpdateItemsResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def list_items_live( self, @@ -3028,87 +1583,19 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/live", - base_url=self._client_wrapper.get_environment().data_api, - method="GET", - params={ - "cmsLocaleId": cms_locale_id, - "offset": offset, - "limit": limit, - "name": name, - "slug": slug, - "lastPublished": convert_and_respect_annotation_metadata( - object_=last_published, annotation=ItemsListItemsLiveRequestLastPublished, direction="write" - ), - "sortBy": sort_by, - "sortOrder": sort_order, - }, + _response = await self._raw_client.list_items_live( + collection_id, + cms_locale_id=cms_locale_id, + offset=offset, + limit=limit, + name=name, + slug=slug, + last_published=last_published, + sort_by=sort_by, + sort_order=sort_order, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItemList, - parse_obj_as( - type_=CollectionItemList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def create_item_live( self, @@ -3173,82 +1660,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/live", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsCreateItemLiveRequestBody, direction="write" - ), - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.create_item_live( + collection_id, request=request, skip_invalid_files=skip_invalid_files, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def delete_items_live( self, @@ -3305,78 +1720,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/live", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - json={ - "items": convert_and_respect_annotation_metadata( - object_=items, annotation=typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.delete_items_live( + collection_id, items=items, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def update_items_live( self, @@ -3469,97 +1816,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/live", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json={ - "items": convert_and_respect_annotation_metadata( - object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.update_items_live( + collection_id, skip_invalid_files=skip_invalid_files, items=items, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItemListNoPagination, - parse_obj_as( - type_=CollectionItemListNoPagination, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def create_items( self, @@ -3641,90 +1901,16 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/bulk", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json={ - "cmsLocaleIds": cms_locale_ids, - "isArchived": is_archived, - "isDraft": is_draft, - "fieldData": convert_and_respect_annotation_metadata( - object_=field_data, annotation=CreateBulkCollectionItemRequestBodyFieldData, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.create_items( + collection_id, + field_data=field_data, + skip_invalid_files=skip_invalid_files, + cms_locale_ids=cms_locale_ids, + is_archived=is_archived, + is_draft=is_draft, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - BulkCollectionItem, - parse_obj_as( - type_=BulkCollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get_item( self, @@ -3779,78 +1965,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "cmsLocaleId": cms_locale_id, - }, - request_options=request_options, + _response = await self._raw_client.get_item( + collection_id, item_id, cms_locale_id=cms_locale_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def delete_item( self, @@ -3904,72 +2022,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - params={ - "cmsLocaleId": cms_locale_id, - }, - request_options=request_options, + _response = await self._raw_client.delete_item( + collection_id, item_id, cms_locale_id=cms_locale_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def update_item( self, @@ -4061,91 +2117,21 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json={ - "id": id, - "cmsLocaleId": cms_locale_id, - "lastPublished": last_published, - "lastUpdated": last_updated, - "createdOn": created_on, - "isArchived": is_archived, - "isDraft": is_draft, - "fieldData": convert_and_respect_annotation_metadata( - object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" - ), - }, + _response = await self._raw_client.update_item( + collection_id, + item_id, + skip_invalid_files=skip_invalid_files, + id=id, + cms_locale_id=cms_locale_id, + last_published=last_published, + last_updated=last_updated, + created_on=created_on, + is_archived=is_archived, + is_draft=is_draft, + field_data=field_data, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get_item_live( self, @@ -4204,78 +2190,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", - base_url=self._client_wrapper.get_environment().data_api, - method="GET", - params={ - "cmsLocaleId": cms_locale_id, - }, - request_options=request_options, + _response = await self._raw_client.get_item_live( + collection_id, item_id, cms_locale_id=cms_locale_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def delete_item_live( self, @@ -4331,72 +2249,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - params={ - "cmsLocaleId": cms_locale_id, - }, - request_options=request_options, + _response = await self._raw_client.delete_item_live( + collection_id, item_id, cms_locale_id=cms_locale_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def update_item_live( self, @@ -4488,101 +2344,21 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - params={ - "skipInvalidFiles": skip_invalid_files, - }, - json={ - "id": id, - "cmsLocaleId": cms_locale_id, - "lastPublished": last_published, - "lastUpdated": last_updated, - "createdOn": created_on, - "isArchived": is_archived, - "isDraft": is_draft, - "fieldData": convert_and_respect_annotation_metadata( - object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" - ), - }, + _response = await self._raw_client.update_item_live( + collection_id, + item_id, + skip_invalid_files=skip_invalid_files, + id=id, + cms_locale_id=cms_locale_id, + last_published=last_published, + last_updated=last_updated, + created_on=created_on, + is_archived=is_archived, + is_draft=is_draft, + field_data=field_data, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CollectionItem, - parse_obj_as( - type_=CollectionItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def publish_item( self, @@ -4638,86 +2414,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(collection_id)}/items/publish", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json=convert_and_respect_annotation_metadata( - object_=request, annotation=ItemsPublishItemRequest, direction="write" - ), - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ItemsPublishItemResponse, - parse_obj_as( - type_=ItemsPublishItemResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.publish_item(collection_id, request=request, request_options=request_options) + return _response.data diff --git a/src/webflow/resources/collections/resources/items/raw_client.py b/src/webflow/resources/collections/resources/items/raw_client.py new file mode 100644 index 0000000..010bbfd --- /dev/null +++ b/src/webflow/resources/collections/resources/items/raw_client.py @@ -0,0 +1,4246 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....core.serialization import convert_and_respect_annotation_metadata +from .....errors.bad_request_error import BadRequestError +from .....errors.conflict_error import ConflictError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.bulk_collection_item import BulkCollectionItem +from .....types.collection_item import CollectionItem +from .....types.collection_item_list import CollectionItemList +from .....types.collection_item_list_no_pagination import CollectionItemListNoPagination +from .....types.collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData +from .....types.collection_item_with_id_input import CollectionItemWithIdInput +from .....types.error import Error +from .....types.items_list_items_live_request_last_published import ItemsListItemsLiveRequestLastPublished +from .....types.items_list_items_request_last_published import ItemsListItemsRequestLastPublished +from .types.create_bulk_collection_item_request_body_field_data import CreateBulkCollectionItemRequestBodyFieldData +from .types.items_create_item_live_request_body import ItemsCreateItemLiveRequestBody +from .types.items_create_item_request_body import ItemsCreateItemRequestBody +from .types.items_delete_items_live_request_items_item import ItemsDeleteItemsLiveRequestItemsItem +from .types.items_delete_items_request_items_item import ItemsDeleteItemsRequestItemsItem +from .types.items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy +from .types.items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder +from .types.items_list_items_request_sort_by import ItemsListItemsRequestSortBy +from .types.items_list_items_request_sort_order import ItemsListItemsRequestSortOrder +from .types.items_publish_item_request import ItemsPublishItemRequest +from .types.items_publish_item_response import ItemsPublishItemResponse +from .types.items_update_items_response import ItemsUpdateItemsResponse +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawItemsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list_items( + self, + collection_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + name: typing.Optional[str] = None, + slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsRequestLastPublished] = None, + sort_by: typing.Optional[ItemsListItemsRequestSortBy] = None, + sort_order: typing.Optional[ItemsListItemsRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CollectionItemList]: + """ + List of all Items within a Collection. + + Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + name : typing.Optional[str] + Filter by the exact name of the item(s) + + slug : typing.Optional[str] + Filter by the exact slug of the item + + last_published : typing.Optional[ItemsListItemsRequestLastPublished] + Filter by the last published date of the item(s) + + sort_by : typing.Optional[ItemsListItemsRequestSortBy] + Sort results by the provided value + + sort_order : typing.Optional[ItemsListItemsRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CollectionItemList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + "offset": offset, + "limit": limit, + "name": name, + "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsRequestLastPublished, direction="write" + ), + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItemList, + parse_obj_as( + type_=CollectionItemList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create_item( + self, + collection_id: str, + *, + request: ItemsCreateItemRequestBody, + skip_invalid_files: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CollectionItem]: + """ + Create Item(s) in a Collection. + + + To create items across multiple locales, please use [this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request : ItemsCreateItemRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CollectionItem] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsCreateItemRequestBody, direction="write" + ), + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete_items( + self, + collection_id: str, + *, + items: typing.Sequence[ItemsDeleteItemsRequestItemsItem], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Delete Items from a Collection. + + Items will only be deleted in the primary locale unless a `cmsLocaleId` is included in the request. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + items : typing.Sequence[ItemsDeleteItemsRequestItemsItem] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[ItemsDeleteItemsRequestItemsItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_items( + self, + collection_id: str, + *, + skip_invalid_files: typing.Optional[bool] = None, + items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ItemsUpdateItemsResponse]: + """ + Update a single item or multiple items in a Collection. + + The limit for this endpoint is 100 items. + + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ItemsUpdateItemsResponse] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ItemsUpdateItemsResponse, + parse_obj_as( + type_=ItemsUpdateItemsResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def list_items_live( + self, + collection_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + name: typing.Optional[str] = None, + slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsLiveRequestLastPublished] = None, + sort_by: typing.Optional[ItemsListItemsLiveRequestSortBy] = None, + sort_order: typing.Optional[ItemsListItemsLiveRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CollectionItemList]: + """ + List all published items in a collection. + + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + + + Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + name : typing.Optional[str] + Filter by the exact name of the item(s) + + slug : typing.Optional[str] + Filter by the exact slug of the item + + last_published : typing.Optional[ItemsListItemsLiveRequestLastPublished] + Filter by the last published date of the item(s) + + sort_by : typing.Optional[ItemsListItemsLiveRequestSortBy] + Sort results by the provided value + + sort_order : typing.Optional[ItemsListItemsLiveRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CollectionItemList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + "offset": offset, + "limit": limit, + "name": name, + "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsLiveRequestLastPublished, direction="write" + ), + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItemList, + parse_obj_as( + type_=CollectionItemList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create_item_live( + self, + collection_id: str, + *, + request: ItemsCreateItemLiveRequestBody, + skip_invalid_files: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CollectionItem]: + """ + Create item(s) in a collection that will be immediately published to the live site. + + + To create items across multiple locales, [please use this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) + + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request : ItemsCreateItemLiveRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CollectionItem] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsCreateItemLiveRequestBody, direction="write" + ), + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete_items_live( + self, + collection_id: str, + *, + items: typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Unpublish up to 100 items from the live site and set the `isDraft` property to `true`. + + Items will only be unpublished in the primary locale unless a `cmsLocaleId` is included in the request. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + items : typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_items_live( + self, + collection_id: str, + *, + skip_invalid_files: typing.Optional[bool] = None, + items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CollectionItemListNoPagination]: + """ + Update a single published item or multiple published items (up to 100) in a Collection + + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CollectionItemListNoPagination] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItemListNoPagination, + parse_obj_as( + type_=CollectionItemListNoPagination, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create_items( + self, + collection_id: str, + *, + field_data: CreateBulkCollectionItemRequestBodyFieldData, + skip_invalid_files: typing.Optional[bool] = None, + cms_locale_ids: typing.Optional[typing.Sequence[str]] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[BulkCollectionItem]: + """ + Create an item or multiple items in a CMS Collection across multiple corresponding locales. + + + - This endpoint can create up to 100 items in a request. + - If the `cmsLocaleIds` parameter is not included in the request, an item will only be created in the primary locale. + + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_data : CreateBulkCollectionItemRequestBodyFieldData + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + cms_locale_ids : typing.Optional[typing.Sequence[str]] + Array of identifiers for the locales where the item will be created + + is_archived : typing.Optional[bool] + Indicates whether the item is archived. + + is_draft : typing.Optional[bool] + Indicates whether the item is in draft state. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[BulkCollectionItem] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/bulk", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json={ + "cmsLocaleIds": cms_locale_ids, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CreateBulkCollectionItemRequestBodyFieldData, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + BulkCollectionItem, + parse_obj_as( + type_=BulkCollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_item( + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CollectionItem]: + """ + Get details of a selected Collection Item. + + Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CollectionItem] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete_item( + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Delete an item from a collection. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + params={ + "cmsLocaleId": cms_locale_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_item( + self, + collection_id: str, + item_id: str, + *, + skip_invalid_files: typing.Optional[bool] = None, + id: typing.Optional[str] = OMIT, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemPatchSingleFieldData] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CollectionItem]: + """ + Update a selected Item in a Collection. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + id : typing.Optional[str] + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published + + last_updated : typing.Optional[str] + The date the item was last updated + + created_on : typing.Optional[str] + The date the item was created + + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived + + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft + + field_data : typing.Optional[CollectionItemPatchSingleFieldData] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CollectionItem] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_item_live( + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CollectionItem]: + """ + Get details of a selected Collection live Item. + + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + + + Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CollectionItem] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete_item_live( + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Unpublish a live item from the site and set the `isDraft` property to `true`. + + For bulk unpublishing, please use [this endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + params={ + "cmsLocaleId": cms_locale_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_item_live( + self, + collection_id: str, + item_id: str, + *, + skip_invalid_files: typing.Optional[bool] = None, + id: typing.Optional[str] = OMIT, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemPatchSingleFieldData] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CollectionItem]: + """ + Update a selected live Item in a Collection. The updates for this Item will be published to the live site. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + id : typing.Optional[str] + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published + + last_updated : typing.Optional[str] + The date the item was last updated + + created_on : typing.Optional[str] + The date the item was created + + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived + + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft + + field_data : typing.Optional[CollectionItemPatchSingleFieldData] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CollectionItem] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def publish_item( + self, + collection_id: str, + *, + request: ItemsPublishItemRequest, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ItemsPublishItemResponse]: + """ + Publish an item or multiple items. + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request : ItemsPublishItemRequest + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ItemsPublishItemResponse] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/publish", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsPublishItemRequest, direction="write" + ), + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ItemsPublishItemResponse, + parse_obj_as( + type_=ItemsPublishItemResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawItemsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list_items( + self, + collection_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + name: typing.Optional[str] = None, + slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsRequestLastPublished] = None, + sort_by: typing.Optional[ItemsListItemsRequestSortBy] = None, + sort_order: typing.Optional[ItemsListItemsRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CollectionItemList]: + """ + List of all Items within a Collection. + + Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + name : typing.Optional[str] + Filter by the exact name of the item(s) + + slug : typing.Optional[str] + Filter by the exact slug of the item + + last_published : typing.Optional[ItemsListItemsRequestLastPublished] + Filter by the last published date of the item(s) + + sort_by : typing.Optional[ItemsListItemsRequestSortBy] + Sort results by the provided value + + sort_order : typing.Optional[ItemsListItemsRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CollectionItemList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + "offset": offset, + "limit": limit, + "name": name, + "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsRequestLastPublished, direction="write" + ), + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItemList, + parse_obj_as( + type_=CollectionItemList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create_item( + self, + collection_id: str, + *, + request: ItemsCreateItemRequestBody, + skip_invalid_files: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CollectionItem]: + """ + Create Item(s) in a Collection. + + + To create items across multiple locales, please use [this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request : ItemsCreateItemRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CollectionItem] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsCreateItemRequestBody, direction="write" + ), + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete_items( + self, + collection_id: str, + *, + items: typing.Sequence[ItemsDeleteItemsRequestItemsItem], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Delete Items from a Collection. + + Items will only be deleted in the primary locale unless a `cmsLocaleId` is included in the request. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + items : typing.Sequence[ItemsDeleteItemsRequestItemsItem] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[ItemsDeleteItemsRequestItemsItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_items( + self, + collection_id: str, + *, + skip_invalid_files: typing.Optional[bool] = None, + items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ItemsUpdateItemsResponse]: + """ + Update a single item or multiple items in a Collection. + + The limit for this endpoint is 100 items. + + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ItemsUpdateItemsResponse] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ItemsUpdateItemsResponse, + parse_obj_as( + type_=ItemsUpdateItemsResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def list_items_live( + self, + collection_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + name: typing.Optional[str] = None, + slug: typing.Optional[str] = None, + last_published: typing.Optional[ItemsListItemsLiveRequestLastPublished] = None, + sort_by: typing.Optional[ItemsListItemsLiveRequestSortBy] = None, + sort_order: typing.Optional[ItemsListItemsLiveRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CollectionItemList]: + """ + List all published items in a collection. + + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + + + Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + name : typing.Optional[str] + Filter by the exact name of the item(s) + + slug : typing.Optional[str] + Filter by the exact slug of the item + + last_published : typing.Optional[ItemsListItemsLiveRequestLastPublished] + Filter by the last published date of the item(s) + + sort_by : typing.Optional[ItemsListItemsLiveRequestSortBy] + Sort results by the provided value + + sort_order : typing.Optional[ItemsListItemsLiveRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CollectionItemList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + "offset": offset, + "limit": limit, + "name": name, + "slug": slug, + "lastPublished": convert_and_respect_annotation_metadata( + object_=last_published, annotation=ItemsListItemsLiveRequestLastPublished, direction="write" + ), + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItemList, + parse_obj_as( + type_=CollectionItemList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create_item_live( + self, + collection_id: str, + *, + request: ItemsCreateItemLiveRequestBody, + skip_invalid_files: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CollectionItem]: + """ + Create item(s) in a collection that will be immediately published to the live site. + + + To create items across multiple locales, [please use this endpoint.](/data/reference/cms/collection-items/staged-items/create-items) + + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request : ItemsCreateItemLiveRequestBody + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CollectionItem] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsCreateItemLiveRequestBody, direction="write" + ), + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete_items_live( + self, + collection_id: str, + *, + items: typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Unpublish up to 100 items from the live site and set the `isDraft` property to `true`. + + Items will only be unpublished in the primary locale unless a `cmsLocaleId` is included in the request. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + items : typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[ItemsDeleteItemsLiveRequestItemsItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_items_live( + self, + collection_id: str, + *, + skip_invalid_files: typing.Optional[bool] = None, + items: typing.Optional[typing.Sequence[CollectionItemWithIdInput]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CollectionItemListNoPagination]: + """ + Update a single published item or multiple published items (up to 100) in a Collection + + Items will only be updated in the primary locale, unless a `cmsLocaleId` is included in the request. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + items : typing.Optional[typing.Sequence[CollectionItemWithIdInput]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CollectionItemListNoPagination] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/live", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json={ + "items": convert_and_respect_annotation_metadata( + object_=items, annotation=typing.Sequence[CollectionItemWithIdInput], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItemListNoPagination, + parse_obj_as( + type_=CollectionItemListNoPagination, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create_items( + self, + collection_id: str, + *, + field_data: CreateBulkCollectionItemRequestBodyFieldData, + skip_invalid_files: typing.Optional[bool] = None, + cms_locale_ids: typing.Optional[typing.Sequence[str]] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[BulkCollectionItem]: + """ + Create an item or multiple items in a CMS Collection across multiple corresponding locales. + + + - This endpoint can create up to 100 items in a request. + - If the `cmsLocaleIds` parameter is not included in the request, an item will only be created in the primary locale. + + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + field_data : CreateBulkCollectionItemRequestBodyFieldData + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + cms_locale_ids : typing.Optional[typing.Sequence[str]] + Array of identifiers for the locales where the item will be created + + is_archived : typing.Optional[bool] + Indicates whether the item is archived. + + is_draft : typing.Optional[bool] + Indicates whether the item is in draft state. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[BulkCollectionItem] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/bulk", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json={ + "cmsLocaleIds": cms_locale_ids, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CreateBulkCollectionItemRequestBodyFieldData, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + BulkCollectionItem, + parse_obj_as( + type_=BulkCollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_item( + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CollectionItem]: + """ + Get details of a selected Collection Item. + + Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CollectionItem] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete_item( + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Delete an item from a collection. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + params={ + "cmsLocaleId": cms_locale_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_item( + self, + collection_id: str, + item_id: str, + *, + skip_invalid_files: typing.Optional[bool] = None, + id: typing.Optional[str] = OMIT, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemPatchSingleFieldData] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CollectionItem]: + """ + Update a selected Item in a Collection. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + id : typing.Optional[str] + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published + + last_updated : typing.Optional[str] + The date the item was last updated + + created_on : typing.Optional[str] + The date the item was created + + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived + + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft + + field_data : typing.Optional[CollectionItemPatchSingleFieldData] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CollectionItem] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_item_live( + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CollectionItem]: + """ + Get details of a selected Collection live Item. + + + Serving data to applications in real-time? Use the Content Delivery API at `api-cdn.webflow.com` for better performance. The CDN-backed endpoint is optimized for high-volume reads, while the Data API is designed for writes and management operations. + + + Required scope | `CMS:read` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CollectionItem] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "cmsLocaleId": cms_locale_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete_item_live( + self, + collection_id: str, + item_id: str, + *, + cms_locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Unpublish a live item from the site and set the `isDraft` property to `true`. + + For bulk unpublishing, please use [this endpoint.](/data/v2.0.0/reference/cms/collection-items/live-items/delete-items-live) + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + cms_locale_id : typing.Optional[str] + Unique identifier for a CMS Locale. This UID is different from the Site locale identifier and is listed as `cmsLocaleId` in the Sites response. To query multiple locales, input a comma separated string. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + params={ + "cmsLocaleId": cms_locale_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_item_live( + self, + collection_id: str, + item_id: str, + *, + skip_invalid_files: typing.Optional[bool] = None, + id: typing.Optional[str] = OMIT, + cms_locale_id: typing.Optional[str] = OMIT, + last_published: typing.Optional[str] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + is_archived: typing.Optional[bool] = OMIT, + is_draft: typing.Optional[bool] = OMIT, + field_data: typing.Optional[CollectionItemPatchSingleFieldData] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CollectionItem]: + """ + Update a selected live Item in a Collection. The updates for this Item will be published to the live site. + + Required scope | `CMS:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + item_id : str + Unique identifier for an Item + + skip_invalid_files : typing.Optional[bool] + When true, invalid files are skipped and processing continues. When false, the entire request fails if any file is invalid. + + id : typing.Optional[str] + Unique identifier for the Item + + cms_locale_id : typing.Optional[str] + Identifier for the locale of the CMS item + + last_published : typing.Optional[str] + The date the item was last published + + last_updated : typing.Optional[str] + The date the item was last updated + + created_on : typing.Optional[str] + The date the item was created + + is_archived : typing.Optional[bool] + Boolean determining if the Item is set to archived + + is_draft : typing.Optional[bool] + Boolean determining if the Item is set to draft + + field_data : typing.Optional[CollectionItemPatchSingleFieldData] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CollectionItem] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/{jsonable_encoder(item_id)}/live", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + params={ + "skipInvalidFiles": skip_invalid_files, + }, + json={ + "id": id, + "cmsLocaleId": cms_locale_id, + "lastPublished": last_published, + "lastUpdated": last_updated, + "createdOn": created_on, + "isArchived": is_archived, + "isDraft": is_draft, + "fieldData": convert_and_respect_annotation_metadata( + object_=field_data, annotation=CollectionItemPatchSingleFieldData, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CollectionItem, + parse_obj_as( + type_=CollectionItem, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def publish_item( + self, + collection_id: str, + *, + request: ItemsPublishItemRequest, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ItemsPublishItemResponse]: + """ + Publish an item or multiple items. + + Required scope | `cms:write` + + Parameters + ---------- + collection_id : str + Unique identifier for a Collection + + request : ItemsPublishItemRequest + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ItemsPublishItemResponse] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(collection_id)}/items/publish", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json=convert_and_respect_annotation_metadata( + object_=request, annotation=ItemsPublishItemRequest, direction="write" + ), + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ItemsPublishItemResponse, + parse_obj_as( + type_=ItemsPublishItemResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/collections/resources/items/types/__init__.py b/src/webflow/resources/collections/resources/items/types/__init__.py index 2d9a604..6350593 100644 --- a/src/webflow/resources/collections/resources/items/types/__init__.py +++ b/src/webflow/resources/collections/resources/items/types/__init__.py @@ -1,28 +1,79 @@ # This file was auto-generated by Fern from our API Definition. -from .create_bulk_collection_item_request_body_field_data import CreateBulkCollectionItemRequestBodyFieldData -from .create_bulk_collection_item_request_body_field_data_item import CreateBulkCollectionItemRequestBodyFieldDataItem -from .item_i_ds import ItemIDs -from .item_i_ds_with_locales import ItemIDsWithLocales -from .items_create_item_live_request_body import ItemsCreateItemLiveRequestBody -from .items_create_item_request_body import ItemsCreateItemRequestBody -from .items_delete_items_live_request_items_item import ItemsDeleteItemsLiveRequestItemsItem -from .items_delete_items_request_items_item import ItemsDeleteItemsRequestItemsItem -from .items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy -from .items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder -from .items_list_items_request_sort_by import ItemsListItemsRequestSortBy -from .items_list_items_request_sort_order import ItemsListItemsRequestSortOrder -from .items_publish_item_request import ItemsPublishItemRequest -from .items_publish_item_request_items_items_item import ItemsPublishItemRequestItemsItemsItem -from .items_publish_item_response import ItemsPublishItemResponse -from .items_update_items_response import ItemsUpdateItemsResponse -from .multiple_items import MultipleItems -from .multiple_live_items import MultipleLiveItems -from .single_cms_item import SingleCmsItem +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .create_bulk_collection_item_request_body_field_data import CreateBulkCollectionItemRequestBodyFieldData + from .create_bulk_collection_item_request_body_field_data_one_item import ( + CreateBulkCollectionItemRequestBodyFieldDataOneItem, + ) + from .item_i_ds import ItemIDs + from .item_i_ds_with_locales import ItemIDsWithLocales + from .items_create_item_live_request_body import ItemsCreateItemLiveRequestBody + from .items_create_item_request_body import ItemsCreateItemRequestBody + from .items_delete_items_live_request_items_item import ItemsDeleteItemsLiveRequestItemsItem + from .items_delete_items_request_items_item import ItemsDeleteItemsRequestItemsItem + from .items_list_items_live_request_sort_by import ItemsListItemsLiveRequestSortBy + from .items_list_items_live_request_sort_order import ItemsListItemsLiveRequestSortOrder + from .items_list_items_request_sort_by import ItemsListItemsRequestSortBy + from .items_list_items_request_sort_order import ItemsListItemsRequestSortOrder + from .items_publish_item_request import ItemsPublishItemRequest + from .items_publish_item_request_items_items_item import ItemsPublishItemRequestItemsItemsItem + from .items_publish_item_response import ItemsPublishItemResponse + from .items_update_items_response import ItemsUpdateItemsResponse + from .multiple_items import MultipleItems + from .multiple_live_items import MultipleLiveItems + from .single_cms_item import SingleCmsItem +_dynamic_imports: typing.Dict[str, str] = { + "CreateBulkCollectionItemRequestBodyFieldData": ".create_bulk_collection_item_request_body_field_data", + "CreateBulkCollectionItemRequestBodyFieldDataOneItem": ".create_bulk_collection_item_request_body_field_data_one_item", + "ItemIDs": ".item_i_ds", + "ItemIDsWithLocales": ".item_i_ds_with_locales", + "ItemsCreateItemLiveRequestBody": ".items_create_item_live_request_body", + "ItemsCreateItemRequestBody": ".items_create_item_request_body", + "ItemsDeleteItemsLiveRequestItemsItem": ".items_delete_items_live_request_items_item", + "ItemsDeleteItemsRequestItemsItem": ".items_delete_items_request_items_item", + "ItemsListItemsLiveRequestSortBy": ".items_list_items_live_request_sort_by", + "ItemsListItemsLiveRequestSortOrder": ".items_list_items_live_request_sort_order", + "ItemsListItemsRequestSortBy": ".items_list_items_request_sort_by", + "ItemsListItemsRequestSortOrder": ".items_list_items_request_sort_order", + "ItemsPublishItemRequest": ".items_publish_item_request", + "ItemsPublishItemRequestItemsItemsItem": ".items_publish_item_request_items_items_item", + "ItemsPublishItemResponse": ".items_publish_item_response", + "ItemsUpdateItemsResponse": ".items_update_items_response", + "MultipleItems": ".multiple_items", + "MultipleLiveItems": ".multiple_live_items", + "SingleCmsItem": ".single_cms_item", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "CreateBulkCollectionItemRequestBodyFieldData", - "CreateBulkCollectionItemRequestBodyFieldDataItem", + "CreateBulkCollectionItemRequestBodyFieldDataOneItem", "ItemIDs", "ItemIDsWithLocales", "ItemsCreateItemLiveRequestBody", diff --git a/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data.py b/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data.py index c4bcb14..cfa74ad 100644 --- a/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data.py +++ b/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data.py @@ -1,9 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing + +from .create_bulk_collection_item_request_body_field_data_one_item import ( + CreateBulkCollectionItemRequestBodyFieldDataOneItem, +) from .single_cms_item import SingleCmsItem -from .create_bulk_collection_item_request_body_field_data_item import CreateBulkCollectionItemRequestBodyFieldDataItem CreateBulkCollectionItemRequestBodyFieldData = typing.Union[ - SingleCmsItem, typing.List[CreateBulkCollectionItemRequestBodyFieldDataItem] + SingleCmsItem, typing.List[CreateBulkCollectionItemRequestBodyFieldDataOneItem] ] diff --git a/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data_item.py b/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data_one_item.py similarity index 73% rename from src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data_item.py rename to src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data_one_item.py index dd6a4f7..0999f96 100644 --- a/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data_item.py +++ b/src/webflow/resources/collections/resources/items/types/create_bulk_collection_item_request_body_field_data_one_item.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ......core.pydantic_utilities import UniversalBaseModel -import pydantic -from ......core.pydantic_utilities import IS_PYDANTIC_V2 import typing +import pydantic +from ......core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + -class CreateBulkCollectionItemRequestBodyFieldDataItem(UniversalBaseModel): +class CreateBulkCollectionItemRequestBodyFieldDataOneItem(UniversalBaseModel): """ A single CMS item to create """ @@ -18,7 +18,7 @@ class CreateBulkCollectionItemRequestBodyFieldDataItem(UniversalBaseModel): slug: str = pydantic.Field() """ - URL slug for the item in your site. + URL slug for the item in your site. Note: Updating the item slug will break all links referencing the old slug. """ diff --git a/src/webflow/resources/collections/resources/items/types/item_i_ds.py b/src/webflow/resources/collections/resources/items/types/item_i_ds.py index b9b138e..f71ca26 100644 --- a/src/webflow/resources/collections/resources/items/types/item_i_ds.py +++ b/src/webflow/resources/collections/resources/items/types/item_i_ds.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ......core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ......core.serialization import FieldMetadata -from ......core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +import typing_extensions +from ......core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ......core.serialization import FieldMetadata class ItemIDs(UniversalBaseModel): @@ -13,7 +13,9 @@ class ItemIDs(UniversalBaseModel): An array of Item IDs in a single locale """ - item_ids: typing_extensions.Annotated[typing.Optional[typing.List[str]], FieldMetadata(alias="itemIds")] = None + item_ids: typing_extensions.Annotated[ + typing.Optional[typing.List[str]], FieldMetadata(alias="itemIds"), pydantic.Field(alias="itemIds") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py b/src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py index ba98ae7..23ad969 100644 --- a/src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py +++ b/src/webflow/resources/collections/resources/items/types/item_i_ds_with_locales.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ......core.pydantic_utilities import UniversalBaseModel import typing -from .items_publish_item_request_items_items_item import ItemsPublishItemRequestItemsItemsItem -from ......core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ......core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .items_publish_item_request_items_items_item import ItemsPublishItemRequestItemsItemsItem class ItemIDsWithLocales(UniversalBaseModel): diff --git a/src/webflow/resources/collections/resources/items/types/items_create_item_live_request_body.py b/src/webflow/resources/collections/resources/items/types/items_create_item_live_request_body.py index 348e0be..7e008a5 100644 --- a/src/webflow/resources/collections/resources/items/types/items_create_item_live_request_body.py +++ b/src/webflow/resources/collections/resources/items/types/items_create_item_live_request_body.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing + from ......types.collection_item import CollectionItem from .multiple_live_items import MultipleLiveItems diff --git a/src/webflow/resources/collections/resources/items/types/items_create_item_request_body.py b/src/webflow/resources/collections/resources/items/types/items_create_item_request_body.py index af4860a..94bd556 100644 --- a/src/webflow/resources/collections/resources/items/types/items_create_item_request_body.py +++ b/src/webflow/resources/collections/resources/items/types/items_create_item_request_body.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing + from ......types.collection_item_post_single import CollectionItemPostSingle from .multiple_items import MultipleItems diff --git a/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py b/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py index 544df88..0fa1b7b 100644 --- a/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py +++ b/src/webflow/resources/collections/resources/items/types/items_delete_items_live_request_items_item.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ......core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic import typing_extensions -import typing +from ......core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ......core.serialization import FieldMetadata -from ......core.pydantic_utilities import IS_PYDANTIC_V2 class ItemsDeleteItemsLiveRequestItemsItem(UniversalBaseModel): @@ -15,11 +15,12 @@ class ItemsDeleteItemsLiveRequestItemsItem(UniversalBaseModel): """ cms_locale_ids: typing_extensions.Annotated[ - typing.Optional[typing.List[str]], FieldMetadata(alias="cmsLocaleIds") - ] = pydantic.Field(default=None) - """ - Array of identifiers for the locales where the item will be created - """ + typing.Optional[typing.List[str]], + FieldMetadata(alias="cmsLocaleIds"), + pydantic.Field( + alias="cmsLocaleIds", description="Array of identifiers for the locales where the item will be created" + ), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/resources/collections/resources/items/types/items_delete_items_request_items_item.py b/src/webflow/resources/collections/resources/items/types/items_delete_items_request_items_item.py index 3b66981..5438d65 100644 --- a/src/webflow/resources/collections/resources/items/types/items_delete_items_request_items_item.py +++ b/src/webflow/resources/collections/resources/items/types/items_delete_items_request_items_item.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ......core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic import typing_extensions -import typing +from ......core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ......core.serialization import FieldMetadata -from ......core.pydantic_utilities import IS_PYDANTIC_V2 class ItemsDeleteItemsRequestItemsItem(UniversalBaseModel): @@ -15,11 +15,12 @@ class ItemsDeleteItemsRequestItemsItem(UniversalBaseModel): """ cms_locale_ids: typing_extensions.Annotated[ - typing.Optional[typing.List[str]], FieldMetadata(alias="cmsLocaleIds") - ] = pydantic.Field(default=None) - """ - Array of identifiers for the locales where the item will be created - """ + typing.Optional[typing.List[str]], + FieldMetadata(alias="cmsLocaleIds"), + pydantic.Field( + alias="cmsLocaleIds", description="Array of identifiers for the locales where the item will be created" + ), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/resources/collections/resources/items/types/items_publish_item_request.py b/src/webflow/resources/collections/resources/items/types/items_publish_item_request.py index 4f7a82b..dc4ca56 100644 --- a/src/webflow/resources/collections/resources/items/types/items_publish_item_request.py +++ b/src/webflow/resources/collections/resources/items/types/items_publish_item_request.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing + from .item_i_ds import ItemIDs from .item_i_ds_with_locales import ItemIDsWithLocales diff --git a/src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py b/src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py index 08b2e17..6798991 100644 --- a/src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py +++ b/src/webflow/resources/collections/resources/items/types/items_publish_item_request_items_items_item.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ......core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic import typing_extensions -import typing +from ......core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ......core.serialization import FieldMetadata -from ......core.pydantic_utilities import IS_PYDANTIC_V2 class ItemsPublishItemRequestItemsItemsItem(UniversalBaseModel): @@ -15,11 +15,12 @@ class ItemsPublishItemRequestItemsItemsItem(UniversalBaseModel): """ cms_locale_ids: typing_extensions.Annotated[ - typing.Optional[typing.List[str]], FieldMetadata(alias="cmsLocaleIds") - ] = pydantic.Field(default=None) - """ - Array of identifiers for the locales where the item will be published - """ + typing.Optional[typing.List[str]], + FieldMetadata(alias="cmsLocaleIds"), + pydantic.Field( + alias="cmsLocaleIds", description="Array of identifiers for the locales where the item will be published" + ), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/resources/collections/resources/items/types/items_publish_item_response.py b/src/webflow/resources/collections/resources/items/types/items_publish_item_response.py index f793223..4e5d67e 100644 --- a/src/webflow/resources/collections/resources/items/types/items_publish_item_response.py +++ b/src/webflow/resources/collections/resources/items/types/items_publish_item_response.py @@ -1,16 +1,18 @@ # This file was auto-generated by Fern from our API Definition. -from ......core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ......core.serialization import FieldMetadata -from ......core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +import typing_extensions +from ......core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ......core.serialization import FieldMetadata class ItemsPublishItemResponse(UniversalBaseModel): published_item_ids: typing_extensions.Annotated[ - typing.Optional[typing.List[str]], FieldMetadata(alias="publishedItemIds") + typing.Optional[typing.List[str]], + FieldMetadata(alias="publishedItemIds"), + pydantic.Field(alias="publishedItemIds"), ] = None errors: typing.Optional[typing.List[str]] = None diff --git a/src/webflow/resources/collections/resources/items/types/items_update_items_response.py b/src/webflow/resources/collections/resources/items/types/items_update_items_response.py index c073f18..137ac3f 100644 --- a/src/webflow/resources/collections/resources/items/types/items_update_items_response.py +++ b/src/webflow/resources/collections/resources/items/types/items_update_items_response.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing + from ......types.collection_item import CollectionItem from ......types.collection_item_list import CollectionItemList diff --git a/src/webflow/resources/collections/resources/items/types/multiple_items.py b/src/webflow/resources/collections/resources/items/types/multiple_items.py index 8700990..44eed57 100644 --- a/src/webflow/resources/collections/resources/items/types/multiple_items.py +++ b/src/webflow/resources/collections/resources/items/types/multiple_items.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ......core.pydantic_utilities import UniversalBaseModel import typing -from ......types.collection_item_post_single import CollectionItemPostSingle + import pydantic -from ......core.pydantic_utilities import IS_PYDANTIC_V2 +from ......core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ......types.collection_item_post_single import CollectionItemPostSingle class MultipleItems(UniversalBaseModel): diff --git a/src/webflow/resources/collections/resources/items/types/multiple_live_items.py b/src/webflow/resources/collections/resources/items/types/multiple_live_items.py index 156fecf..8661342 100644 --- a/src/webflow/resources/collections/resources/items/types/multiple_live_items.py +++ b/src/webflow/resources/collections/resources/items/types/multiple_live_items.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ......core.pydantic_utilities import UniversalBaseModel import typing -from ......types.collection_item import CollectionItem + import pydantic -from ......core.pydantic_utilities import IS_PYDANTIC_V2 +from ......core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ......types.collection_item import CollectionItem class MultipleLiveItems(UniversalBaseModel): diff --git a/src/webflow/resources/collections/resources/items/types/single_cms_item.py b/src/webflow/resources/collections/resources/items/types/single_cms_item.py index b64f1a4..176d013 100644 --- a/src/webflow/resources/collections/resources/items/types/single_cms_item.py +++ b/src/webflow/resources/collections/resources/items/types/single_cms_item.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ......core.pydantic_utilities import UniversalBaseModel -import pydantic -from ......core.pydantic_utilities import IS_PYDANTIC_V2 import typing +import pydantic +from ......core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + class SingleCmsItem(UniversalBaseModel): name: str = pydantic.Field() @@ -14,7 +14,7 @@ class SingleCmsItem(UniversalBaseModel): slug: str = pydantic.Field() """ - URL slug for the item in your site. + URL slug for the item in your site. Note: Updating the item slug will break all links referencing the old slug. """ diff --git a/src/webflow/resources/components/__init__.py b/src/webflow/resources/components/__init__.py index 36f01b7..7b65fd3 100644 --- a/src/webflow/resources/components/__init__.py +++ b/src/webflow/resources/components/__init__.py @@ -1,11 +1,45 @@ # This file was auto-generated by Fern from our API Definition. -from .types import ( - ComponentDomWriteNodesItem, - ComponentPropertiesWritePropertiesItem, - ComponentsUpdateContentResponse, - ComponentsUpdatePropertiesResponse, -) +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import ( + ComponentDomWriteNodesItem, + ComponentPropertiesWritePropertiesItem, + ComponentsUpdateContentResponse, + ComponentsUpdatePropertiesResponse, + ) +_dynamic_imports: typing.Dict[str, str] = { + "ComponentDomWriteNodesItem": ".types", + "ComponentPropertiesWritePropertiesItem": ".types", + "ComponentsUpdateContentResponse": ".types", + "ComponentsUpdatePropertiesResponse": ".types", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "ComponentDomWriteNodesItem", diff --git a/src/webflow/resources/components/client.py b/src/webflow/resources/components/client.py index 5437017..a9584d8 100644 --- a/src/webflow/resources/components/client.py +++ b/src/webflow/resources/components/client.py @@ -1,28 +1,17 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ...core.client_wrapper import SyncClientWrapper + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions -from ...types.component_list import ComponentList -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.not_found_error import NotFoundError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError from ...types.component_dom import ComponentDom -from .types.component_dom_write_nodes_item import ComponentDomWriteNodesItem -from .types.components_update_content_response import ComponentsUpdateContentResponse -from ...core.serialization import convert_and_respect_annotation_metadata -from ...errors.forbidden_error import ForbiddenError +from ...types.component_list import ComponentList from ...types.component_properties import ComponentProperties +from .raw_client import AsyncRawComponentsClient, RawComponentsClient +from .types.component_dom_write_nodes_item import ComponentDomWriteNodesItem from .types.component_properties_write_properties_item import ComponentPropertiesWritePropertiesItem +from .types.components_update_content_response import ComponentsUpdateContentResponse from .types.components_update_properties_response import ComponentsUpdatePropertiesResponse -from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -30,7 +19,18 @@ class ComponentsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawComponentsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawComponentsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawComponentsClient + """ + return self._raw_client def list( self, @@ -82,80 +82,10 @@ def list( offset=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/components", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "branchId": branch_id, - "limit": limit, - "offset": offset, - }, - request_options=request_options, + _response = self._raw_client.list( + site_id, branch_id=branch_id, limit=limit, offset=offset, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ComponentList, - parse_obj_as( - type_=ComponentList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get_content( self, @@ -222,81 +152,16 @@ def get_content( offset=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "branchId": branch_id, - "limit": limit, - "offset": offset, - }, + _response = self._raw_client.get_content( + site_id, + component_id, + locale_id=locale_id, + branch_id=branch_id, + limit=limit, + offset=offset, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ComponentDom, - parse_obj_as( - type_=ComponentDom, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def update_content( self, @@ -417,98 +282,15 @@ def update_content( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "localeId": locale_id, - "branchId": branch_id, - }, - json={ - "nodes": convert_and_respect_annotation_metadata( - object_=nodes, annotation=typing.Sequence[ComponentDomWriteNodesItem], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.update_content( + site_id, + component_id, + nodes=nodes, + locale_id=locale_id, + branch_id=branch_id, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ComponentsUpdateContentResponse, - parse_obj_as( - type_=ComponentsUpdateContentResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get_properties( self, @@ -574,81 +356,16 @@ def get_properties( offset=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "branchId": branch_id, - "limit": limit, - "offset": offset, - }, + _response = self._raw_client.get_properties( + site_id, + component_id, + locale_id=locale_id, + branch_id=branch_id, + limit=limit, + offset=offset, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ComponentProperties, - parse_obj_as( - type_=ComponentProperties, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def update_properties( self, @@ -723,95 +440,31 @@ def update_properties( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "localeId": locale_id, - "branchId": branch_id, - }, - json={ - "properties": convert_and_respect_annotation_metadata( - object_=properties, - annotation=typing.Sequence[ComponentPropertiesWritePropertiesItem], - direction="write", - ), - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.update_properties( + site_id, + component_id, + properties=properties, + locale_id=locale_id, + branch_id=branch_id, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ComponentsUpdatePropertiesResponse, - parse_obj_as( - type_=ComponentsUpdatePropertiesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data class AsyncComponentsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawComponentsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawComponentsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawComponentsClient + """ + return self._raw_client async def list( self, @@ -871,80 +524,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/components", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "branchId": branch_id, - "limit": limit, - "offset": offset, - }, - request_options=request_options, + _response = await self._raw_client.list( + site_id, branch_id=branch_id, limit=limit, offset=offset, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ComponentList, - parse_obj_as( - type_=ComponentList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get_content( self, @@ -1019,81 +602,16 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "branchId": branch_id, - "limit": limit, - "offset": offset, - }, + _response = await self._raw_client.get_content( + site_id, + component_id, + locale_id=locale_id, + branch_id=branch_id, + limit=limit, + offset=offset, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ComponentDom, - parse_obj_as( - type_=ComponentDom, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def update_content( self, @@ -1222,98 +740,15 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "localeId": locale_id, - "branchId": branch_id, - }, - json={ - "nodes": convert_and_respect_annotation_metadata( - object_=nodes, annotation=typing.Sequence[ComponentDomWriteNodesItem], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.update_content( + site_id, + component_id, + nodes=nodes, + locale_id=locale_id, + branch_id=branch_id, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ComponentsUpdateContentResponse, - parse_obj_as( - type_=ComponentsUpdateContentResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get_properties( self, @@ -1387,81 +822,16 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "branchId": branch_id, - "limit": limit, - "offset": offset, - }, + _response = await self._raw_client.get_properties( + site_id, + component_id, + locale_id=locale_id, + branch_id=branch_id, + limit=limit, + offset=offset, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ComponentProperties, - parse_obj_as( - type_=ComponentProperties, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def update_properties( self, @@ -1544,87 +914,12 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "localeId": locale_id, - "branchId": branch_id, - }, - json={ - "properties": convert_and_respect_annotation_metadata( - object_=properties, - annotation=typing.Sequence[ComponentPropertiesWritePropertiesItem], - direction="write", - ), - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.update_properties( + site_id, + component_id, + properties=properties, + locale_id=locale_id, + branch_id=branch_id, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ComponentsUpdatePropertiesResponse, - parse_obj_as( - type_=ComponentsUpdatePropertiesResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data diff --git a/src/webflow/resources/components/raw_client.py b/src/webflow/resources/components/raw_client.py new file mode 100644 index 0000000..caf0799 --- /dev/null +++ b/src/webflow/resources/components/raw_client.py @@ -0,0 +1,1417 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...core.serialization import convert_and_respect_annotation_metadata +from ...errors.bad_request_error import BadRequestError +from ...errors.forbidden_error import ForbiddenError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.component_dom import ComponentDom +from ...types.component_list import ComponentList +from ...types.component_properties import ComponentProperties +from ...types.error import Error +from .types.component_dom_write_nodes_item import ComponentDomWriteNodesItem +from .types.component_properties_write_properties_item import ComponentPropertiesWritePropertiesItem +from .types.components_update_content_response import ComponentsUpdateContentResponse +from .types.components_update_properties_response import ComponentsUpdatePropertiesResponse +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawComponentsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + site_id: str, + *, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ComponentList]: + """ + List of all components for a site. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ComponentList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "branchId": branch_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ComponentList, + parse_obj_as( + type_=ComponentList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_content( + self, + site_id: str, + component_id: str, + *, + locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ComponentDom]: + """ + Get static content from a component definition. This includes text nodes, image nodes, select nodes, text input nodes, submit button nodes, and nested component instances. + To retrieve dynamic content set by component properties, use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + + If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ComponentDom] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "branchId": branch_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ComponentDom, + parse_obj_as( + type_=ComponentDom, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_content( + self, + site_id: str, + component_id: str, + *, + nodes: typing.Sequence[ComponentDomWriteNodesItem], + locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ComponentsUpdateContentResponse]: + """ + This endpoint updates content within a component defintion for **secondary locales**. It supports updating up to 1000 nodes in a single request. + + Before making updates: + 1. Use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint to identify available content nodes and their types. + 2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + 3. DOM elements may include a `data-w-id` attribute. This attribute is used by Webflow to maintain custom attributes and links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. + + + This endpoint is specifically for localizing component definitions. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + + Required scope | `components:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + nodes : typing.Sequence[ComponentDomWriteNodesItem] + List of DOM Nodes with the new content that will be updated in each node. + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ComponentsUpdateContentResponse] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "localeId": locale_id, + "branchId": branch_id, + }, + json={ + "nodes": convert_and_respect_annotation_metadata( + object_=nodes, annotation=typing.Sequence[ComponentDomWriteNodesItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ComponentsUpdateContentResponse, + parse_obj_as( + type_=ComponentsUpdateContentResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_properties( + self, + site_id: str, + component_id: str, + *, + locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ComponentProperties]: + """ + Get the default property values of a component definition. + + If you do not include a `localeId` in your request, the response will return any properties that can be localized from the Primary locale. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ComponentProperties] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "branchId": branch_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ComponentProperties, + parse_obj_as( + type_=ComponentProperties, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_properties( + self, + site_id: str, + component_id: str, + *, + properties: typing.Sequence[ComponentPropertiesWritePropertiesItem], + locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ComponentsUpdatePropertiesResponse]: + """ + Update the default property values of a component definition in a specificed locale. + + Before making updates: + 1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify properties that can be updated in a secondary locale. + 2. Rich Text properties may include a `data-w-id` attribute. This attribute is used by Webflow to maintain links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. + + The request requires a secondary locale ID. If a `localeId` is missing, the request will not be processed and will result in an error. + + Required scope | `components:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + properties : typing.Sequence[ComponentPropertiesWritePropertiesItem] + A list of component properties to update within the specified secondary locale. + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ComponentsUpdatePropertiesResponse] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "localeId": locale_id, + "branchId": branch_id, + }, + json={ + "properties": convert_and_respect_annotation_metadata( + object_=properties, + annotation=typing.Sequence[ComponentPropertiesWritePropertiesItem], + direction="write", + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ComponentsUpdatePropertiesResponse, + parse_obj_as( + type_=ComponentsUpdatePropertiesResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawComponentsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + site_id: str, + *, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ComponentList]: + """ + List of all components for a site. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ComponentList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "branchId": branch_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ComponentList, + parse_obj_as( + type_=ComponentList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_content( + self, + site_id: str, + component_id: str, + *, + locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ComponentDom]: + """ + Get static content from a component definition. This includes text nodes, image nodes, select nodes, text input nodes, submit button nodes, and nested component instances. + To retrieve dynamic content set by component properties, use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + + If you do not provide a Locale ID in your request, the response will return any content that can be localized from the Primary locale. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ComponentDom] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "branchId": branch_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ComponentDom, + parse_obj_as( + type_=ComponentDom, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_content( + self, + site_id: str, + component_id: str, + *, + nodes: typing.Sequence[ComponentDomWriteNodesItem], + locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ComponentsUpdateContentResponse]: + """ + This endpoint updates content within a component defintion for **secondary locales**. It supports updating up to 1000 nodes in a single request. + + Before making updates: + 1. Use the [get component content](/data/reference/pages-and-components/components/get-content) endpoint to identify available content nodes and their types. + 2. If your component definition has a component instance nested within it, retrieve the nested component instance's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + 3. DOM elements may include a `data-w-id` attribute. This attribute is used by Webflow to maintain custom attributes and links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. + + + This endpoint is specifically for localizing component definitions. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + + Required scope | `components:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + nodes : typing.Sequence[ComponentDomWriteNodesItem] + List of DOM Nodes with the new content that will be updated in each node. + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ComponentsUpdateContentResponse] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/dom", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "localeId": locale_id, + "branchId": branch_id, + }, + json={ + "nodes": convert_and_respect_annotation_metadata( + object_=nodes, annotation=typing.Sequence[ComponentDomWriteNodesItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ComponentsUpdateContentResponse, + parse_obj_as( + type_=ComponentsUpdateContentResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_properties( + self, + site_id: str, + component_id: str, + *, + locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ComponentProperties]: + """ + Get the default property values of a component definition. + + If you do not include a `localeId` in your request, the response will return any properties that can be localized from the Primary locale. + + Required scope | `components:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ComponentProperties] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "branchId": branch_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ComponentProperties, + parse_obj_as( + type_=ComponentProperties, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_properties( + self, + site_id: str, + component_id: str, + *, + properties: typing.Sequence[ComponentPropertiesWritePropertiesItem], + locale_id: typing.Optional[str] = None, + branch_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ComponentsUpdatePropertiesResponse]: + """ + Update the default property values of a component definition in a specificed locale. + + Before making updates: + 1. Use the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint to identify properties that can be updated in a secondary locale. + 2. Rich Text properties may include a `data-w-id` attribute. This attribute is used by Webflow to maintain links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. + + The request requires a secondary locale ID. If a `localeId` is missing, the request will not be processed and will result in an error. + + Required scope | `components:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + component_id : str + Unique identifier for a Component + + properties : typing.Sequence[ComponentPropertiesWritePropertiesItem] + A list of component properties to update within the specified secondary locale. + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + branch_id : typing.Optional[str] + Scope the operation to work on a specific branch. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ComponentsUpdatePropertiesResponse] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/components/{jsonable_encoder(component_id)}/properties", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "localeId": locale_id, + "branchId": branch_id, + }, + json={ + "properties": convert_and_respect_annotation_metadata( + object_=properties, + annotation=typing.Sequence[ComponentPropertiesWritePropertiesItem], + direction="write", + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ComponentsUpdatePropertiesResponse, + parse_obj_as( + type_=ComponentsUpdatePropertiesResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/components/types/__init__.py b/src/webflow/resources/components/types/__init__.py index dc8d684..d3d0a32 100644 --- a/src/webflow/resources/components/types/__init__.py +++ b/src/webflow/resources/components/types/__init__.py @@ -1,9 +1,43 @@ # This file was auto-generated by Fern from our API Definition. -from .component_dom_write_nodes_item import ComponentDomWriteNodesItem -from .component_properties_write_properties_item import ComponentPropertiesWritePropertiesItem -from .components_update_content_response import ComponentsUpdateContentResponse -from .components_update_properties_response import ComponentsUpdatePropertiesResponse +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .component_dom_write_nodes_item import ComponentDomWriteNodesItem + from .component_properties_write_properties_item import ComponentPropertiesWritePropertiesItem + from .components_update_content_response import ComponentsUpdateContentResponse + from .components_update_properties_response import ComponentsUpdatePropertiesResponse +_dynamic_imports: typing.Dict[str, str] = { + "ComponentDomWriteNodesItem": ".component_dom_write_nodes_item", + "ComponentPropertiesWritePropertiesItem": ".component_properties_write_properties_item", + "ComponentsUpdateContentResponse": ".components_update_content_response", + "ComponentsUpdatePropertiesResponse": ".components_update_properties_response", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "ComponentDomWriteNodesItem", diff --git a/src/webflow/resources/components/types/component_dom_write_nodes_item.py b/src/webflow/resources/components/types/component_dom_write_nodes_item.py index 1b1789c..8bb5e53 100644 --- a/src/webflow/resources/components/types/component_dom_write_nodes_item.py +++ b/src/webflow/resources/components/types/component_dom_write_nodes_item.py @@ -1,12 +1,13 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ....types.text_node_write import TextNodeWrite + from ....types.component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite +from ....types.search_button_node_write import SearchButtonNodeWrite from ....types.select import Select -from ....types.text_input_node_write import TextInputNodeWrite from ....types.submit_button_node_write import SubmitButtonNodeWrite -from ....types.search_button_node_write import SearchButtonNodeWrite +from ....types.text_input_node_write import TextInputNodeWrite +from ....types.text_node_write import TextNodeWrite ComponentDomWriteNodesItem = typing.Union[ TextNodeWrite, diff --git a/src/webflow/resources/components/types/component_properties_write_properties_item.py b/src/webflow/resources/components/types/component_properties_write_properties_item.py index b4f8f50..30da057 100644 --- a/src/webflow/resources/components/types/component_properties_write_properties_item.py +++ b/src/webflow/resources/components/types/component_properties_write_properties_item.py @@ -1,26 +1,26 @@ # This file was auto-generated by Fern from our API Definition. -from ....core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ....core.serialization import FieldMetadata -import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2 -import typing class ComponentPropertiesWritePropertiesItem(UniversalBaseModel): - property_id: typing_extensions.Annotated[str, FieldMetadata(alias="propertyId")] = pydantic.Field() - """ - The ID of the property. - """ - + property_id: typing_extensions.Annotated[ + str, + FieldMetadata(alias="propertyId"), + pydantic.Field(alias="propertyId", description="The ID of the property."), + ] text: str = pydantic.Field() """ The new string or HTML value used to update the component property in the secondary locale. The provided value must be compatible with the type of the component property. - For example, attempting to update a single-line plain-text property with a multi-line + For example, attempting to update a single-line plain-text property with a multi-line value will result in an error. """ diff --git a/src/webflow/resources/components/types/components_update_content_response.py b/src/webflow/resources/components/types/components_update_content_response.py index 6129dda..9021766 100644 --- a/src/webflow/resources/components/types/components_update_content_response.py +++ b/src/webflow/resources/components/types/components_update_content_response.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ....core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class ComponentsUpdateContentResponse(UniversalBaseModel): diff --git a/src/webflow/resources/components/types/components_update_properties_response.py b/src/webflow/resources/components/types/components_update_properties_response.py index b0c8824..7dffd8b 100644 --- a/src/webflow/resources/components/types/components_update_properties_response.py +++ b/src/webflow/resources/components/types/components_update_properties_response.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ....core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class ComponentsUpdatePropertiesResponse(UniversalBaseModel): diff --git a/src/webflow/resources/ecommerce/__init__.py b/src/webflow/resources/ecommerce/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/ecommerce/__init__.py +++ b/src/webflow/resources/ecommerce/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/ecommerce/client.py b/src/webflow/resources/ecommerce/client.py index 04ddba6..e62f87b 100644 --- a/src/webflow/resources/ecommerce/client.py +++ b/src/webflow/resources/ecommerce/client.py @@ -1,27 +1,27 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.client_wrapper import SyncClientWrapper import typing + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions from ...types.ecommerce_settings import EcommerceSettings -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.forbidden_error import ForbiddenError -from ...errors.not_found_error import NotFoundError -from ...errors.conflict_error import ConflictError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ...core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawEcommerceClient, RawEcommerceClient class EcommerceClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawEcommerceClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawEcommerceClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawEcommerceClient + """ + return self._raw_client def get_settings( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -55,100 +55,24 @@ def get_settings( site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - EcommerceSettings, - parse_obj_as( - type_=EcommerceSettings, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get_settings(site_id, request_options=request_options) + return _response.data class AsyncEcommerceClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawEcommerceClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawEcommerceClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawEcommerceClient + """ + return self._raw_client async def get_settings( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -190,92 +114,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - EcommerceSettings, - parse_obj_as( - type_=EcommerceSettings, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get_settings(site_id, request_options=request_options) + return _response.data diff --git a/src/webflow/resources/ecommerce/raw_client.py b/src/webflow/resources/ecommerce/raw_client.py new file mode 100644 index 0000000..4aa1da3 --- /dev/null +++ b/src/webflow/resources/ecommerce/raw_client.py @@ -0,0 +1,278 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...errors.bad_request_error import BadRequestError +from ...errors.conflict_error import ConflictError +from ...errors.forbidden_error import ForbiddenError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.ecommerce_settings import EcommerceSettings +from ...types.error import Error +from pydantic import ValidationError + + +class RawEcommerceClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_settings( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[EcommerceSettings]: + """ + Retrieve ecommerce settings for a site. + + Required scope | `ecommerce:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[EcommerceSettings] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + EcommerceSettings, + parse_obj_as( + type_=EcommerceSettings, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawEcommerceClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_settings( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[EcommerceSettings]: + """ + Retrieve ecommerce settings for a site. + + Required scope | `ecommerce:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[EcommerceSettings] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/ecommerce/settings", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + EcommerceSettings, + parse_obj_as( + type_=EcommerceSettings, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/forms/__init__.py b/src/webflow/resources/forms/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/forms/__init__.py +++ b/src/webflow/resources/forms/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/forms/client.py b/src/webflow/resources/forms/client.py index 40741cb..f49ab25 100644 --- a/src/webflow/resources/forms/client.py +++ b/src/webflow/resources/forms/client.py @@ -1,25 +1,14 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ...core.client_wrapper import SyncClientWrapper + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions -from ...types.form_list import FormList -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.forbidden_error import ForbiddenError -from ...errors.not_found_error import NotFoundError -from ...errors.conflict_error import ConflictError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError from ...types.form import Form -from ...types.form_submission_list import FormSubmissionList +from ...types.form_list import FormList from ...types.form_submission import FormSubmission -from ...core.client_wrapper import AsyncClientWrapper +from ...types.form_submission_list import FormSubmissionList +from .raw_client import AsyncRawFormsClient, RawFormsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -27,7 +16,18 @@ class FormsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawFormsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawFormsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawFormsClient + """ + return self._raw_client def list( self, @@ -74,99 +74,8 @@ def list( offset=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/forms", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "limit": limit, - "offset": offset, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormList, - parse_obj_as( - type_=FormList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.list(site_id, limit=limit, offset=offset, request_options=request_options) + return _response.data def get(self, form_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Form: """ @@ -198,85 +107,8 @@ def get(self, form_id: str, *, request_options: typing.Optional[RequestOptions] form_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"forms/{jsonable_encoder(form_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Form, - parse_obj_as( - type_=Form, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get(form_id, request_options=request_options) + return _response.data def list_submissions( self, @@ -329,89 +161,10 @@ def list_submissions( limit=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"forms/{jsonable_encoder(form_id)}/submissions", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "offset": offset, - "limit": limit, - }, - request_options=request_options, + _response = self._raw_client.list_submissions( + form_id, offset=offset, limit=limit, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmissionList, - parse_obj_as( - type_=FormSubmissionList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get_submission( self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -445,85 +198,8 @@ def get_submission( form_submission_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmission, - parse_obj_as( - type_=FormSubmission, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get_submission(form_submission_id, request_options=request_options) + return _response.data def delete_submission( self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -557,95 +233,14 @@ def delete_submission( form_submission_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete_submission(form_submission_id, request_options=request_options) + return _response.data def update_submission( self, form_submission_id: str, *, - form_submission_data: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + form_submission_data: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> FormSubmission: """ @@ -658,7 +253,7 @@ def update_submission( form_submission_id : str Unique identifier for a Form Submission - form_submission_data : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] An existing **hidden field** defined on the form schema, and the corresponding value to set request_options : typing.Optional[RequestOptions] @@ -680,107 +275,26 @@ def update_submission( form_submission_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "formSubmissionData": form_submission_data, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.update_submission( + form_submission_id, form_submission_data=form_submission_data, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmission, - parse_obj_as( - type_=FormSubmission, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data class AsyncFormsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawFormsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawFormsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawFormsClient + """ + return self._raw_client async def list( self, @@ -835,99 +349,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/forms", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "limit": limit, - "offset": offset, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormList, - parse_obj_as( - type_=FormList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.list(site_id, limit=limit, offset=offset, request_options=request_options) + return _response.data async def get(self, form_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Form: """ @@ -967,85 +390,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"forms/{jsonable_encoder(form_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Form, - parse_obj_as( - type_=Form, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get(form_id, request_options=request_options) + return _response.data async def list_submissions( self, @@ -1106,89 +452,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"forms/{jsonable_encoder(form_id)}/submissions", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "offset": offset, - "limit": limit, - }, - request_options=request_options, + _response = await self._raw_client.list_submissions( + form_id, offset=offset, limit=limit, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmissionList, - parse_obj_as( - type_=FormSubmissionList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get_submission( self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -1230,85 +497,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmission, - parse_obj_as( - type_=FormSubmission, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get_submission(form_submission_id, request_options=request_options) + return _response.data async def delete_submission( self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -1350,95 +540,14 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.delete_submission(form_submission_id, request_options=request_options) + return _response.data async def update_submission( self, form_submission_id: str, *, - form_submission_data: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + form_submission_data: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> FormSubmission: """ @@ -1451,7 +560,7 @@ async def update_submission( form_submission_id : str Unique identifier for a Form Submission - form_submission_data : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] An existing **hidden field** defined on the form schema, and the corresponding value to set request_options : typing.Optional[RequestOptions] @@ -1481,99 +590,7 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "formSubmissionData": form_submission_data, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.update_submission( + form_submission_id, form_submission_data=form_submission_data, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmission, - parse_obj_as( - type_=FormSubmission, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data diff --git a/src/webflow/resources/forms/raw_client.py b/src/webflow/resources/forms/raw_client.py new file mode 100644 index 0000000..aa85c4e --- /dev/null +++ b/src/webflow/resources/forms/raw_client.py @@ -0,0 +1,1532 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...errors.bad_request_error import BadRequestError +from ...errors.conflict_error import ConflictError +from ...errors.forbidden_error import ForbiddenError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error +from ...types.form import Form +from ...types.form_list import FormList +from ...types.form_submission import FormSubmission +from ...types.form_submission_list import FormSubmissionList +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawFormsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + site_id: str, + *, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[FormList]: + """ + List forms for a given site. + + Required scope | `forms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[FormList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/forms", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormList, + parse_obj_as( + type_=FormList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get(self, form_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Form]: + """ + Get information about a given form. + + Required scope | `forms:read` + + Parameters + ---------- + form_id : str + Unique identifier for a Form + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Form] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"forms/{jsonable_encoder(form_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Form, + parse_obj_as( + type_=Form, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def list_submissions( + self, + form_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[FormSubmissionList]: + """ + List form submissions for a given form + + + When a form is used in a component definition, each instance of the form is considered a unique form. + + To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. + + + Required scope | `forms:read` + + Parameters + ---------- + form_id : str + Unique identifier for a Form + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[FormSubmissionList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"forms/{jsonable_encoder(form_id)}/submissions", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmissionList, + parse_obj_as( + type_=FormSubmissionList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_submission( + self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[FormSubmission]: + """ + Get information about a given form submissio. + + Required scope | `forms:read` + + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[FormSubmission] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete_submission( + self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + Delete a form submission + + + Required scope | `forms:write` + + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_submission( + self, + form_submission_id: str, + *, + form_submission_data: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[FormSubmission]: + """ + Update hidden fields on a form submission + + Required scope | `forms:write` + + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] + An existing **hidden field** defined on the form schema, and the corresponding value to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[FormSubmission] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "formSubmissionData": form_submission_data, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawFormsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + site_id: str, + *, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[FormList]: + """ + List forms for a given site. + + Required scope | `forms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[FormList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/forms", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormList, + parse_obj_as( + type_=FormList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get( + self, form_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Form]: + """ + Get information about a given form. + + Required scope | `forms:read` + + Parameters + ---------- + form_id : str + Unique identifier for a Form + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Form] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"forms/{jsonable_encoder(form_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Form, + parse_obj_as( + type_=Form, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def list_submissions( + self, + form_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[FormSubmissionList]: + """ + List form submissions for a given form + + + When a form is used in a component definition, each instance of the form is considered a unique form. + + To get a combined list of submissions for a form that appears across multiple component instances, use the [List Form Submissions by Site](/data/reference/forms/form-submissions/list-submissions-by-site) endpoint. + + + Required scope | `forms:read` + + Parameters + ---------- + form_id : str + Unique identifier for a Form + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[FormSubmissionList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"forms/{jsonable_encoder(form_id)}/submissions", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmissionList, + parse_obj_as( + type_=FormSubmissionList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_submission( + self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[FormSubmission]: + """ + Get information about a given form submissio. + + Required scope | `forms:read` + + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[FormSubmission] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete_submission( + self, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Delete a form submission + + + Required scope | `forms:write` + + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_submission( + self, + form_submission_id: str, + *, + form_submission_data: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[FormSubmission]: + """ + Update hidden fields on a form submission + + Required scope | `forms:write` + + Parameters + ---------- + form_submission_id : str + Unique identifier for a Form Submission + + form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] + An existing **hidden field** defined on the form schema, and the corresponding value to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[FormSubmission] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "formSubmissionData": form_submission_data, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/inventory/__init__.py b/src/webflow/resources/inventory/__init__.py index e76ae2e..018e6a1 100644 --- a/src/webflow/resources/inventory/__init__.py +++ b/src/webflow/resources/inventory/__init__.py @@ -1,5 +1,37 @@ # This file was auto-generated by Fern from our API Definition. -from .types import EcommInventoryChangedPayload, InventoryUpdateRequestInventoryType +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import EcommInventoryChangedPayload, InventoryUpdateRequestInventoryType +_dynamic_imports: typing.Dict[str, str] = { + "EcommInventoryChangedPayload": ".types", + "InventoryUpdateRequestInventoryType": ".types", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["EcommInventoryChangedPayload", "InventoryUpdateRequestInventoryType"] diff --git a/src/webflow/resources/inventory/client.py b/src/webflow/resources/inventory/client.py index db582a9..51c9454 100644 --- a/src/webflow/resources/inventory/client.py +++ b/src/webflow/resources/inventory/client.py @@ -1,23 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ...core.client_wrapper import SyncClientWrapper + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions from ...types.inventory_item import InventoryItem -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.forbidden_error import ForbiddenError -from ...errors.not_found_error import NotFoundError -from ...errors.conflict_error import ConflictError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError +from .raw_client import AsyncRawInventoryClient, RawInventoryClient from .types.inventory_update_request_inventory_type import InventoryUpdateRequestInventoryType -from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -25,7 +14,18 @@ class InventoryClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawInventoryClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawInventoryClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawInventoryClient + """ + return self._raw_client def list( self, sku_collection_id: str, sku_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -63,95 +63,8 @@ def list( sku_id="5e8518516e147040726cc415", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - InventoryItem, - parse_obj_as( - type_=InventoryItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.list(sku_collection_id, sku_id, request_options=request_options) + return _response.data def update( self, @@ -210,109 +123,31 @@ def update( inventory_type="infinite", ) """ - _response = self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "inventoryType": inventory_type, - "updateQuantity": update_quantity, - "quantity": quantity, - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.update( + sku_collection_id, + sku_id, + inventory_type=inventory_type, + update_quantity=update_quantity, + quantity=quantity, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - InventoryItem, - parse_obj_as( - type_=InventoryItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data class AsyncInventoryClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawInventoryClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawInventoryClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawInventoryClient + """ + return self._raw_client async def list( self, sku_collection_id: str, sku_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -358,95 +193,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - InventoryItem, - parse_obj_as( - type_=InventoryItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.list(sku_collection_id, sku_id, request_options=request_options) + return _response.data async def update( self, @@ -513,101 +261,12 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "inventoryType": inventory_type, - "updateQuantity": update_quantity, - "quantity": quantity, - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.update( + sku_collection_id, + sku_id, + inventory_type=inventory_type, + update_quantity=update_quantity, + quantity=quantity, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - InventoryItem, - parse_obj_as( - type_=InventoryItem, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data diff --git a/src/webflow/resources/inventory/raw_client.py b/src/webflow/resources/inventory/raw_client.py new file mode 100644 index 0000000..af0c454 --- /dev/null +++ b/src/webflow/resources/inventory/raw_client.py @@ -0,0 +1,598 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...errors.bad_request_error import BadRequestError +from ...errors.conflict_error import ConflictError +from ...errors.forbidden_error import ForbiddenError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error +from ...types.inventory_item import InventoryItem +from .types.inventory_update_request_inventory_type import InventoryUpdateRequestInventoryType +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawInventoryClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, sku_collection_id: str, sku_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[InventoryItem]: + """ + List the current inventory levels for a particular SKU item. + + Required scope | `ecommerce:read` + + Parameters + ---------- + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. + + sku_id : str + Unique identifier for a SKU + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[InventoryItem] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + InventoryItem, + parse_obj_as( + type_=InventoryItem, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update( + self, + sku_collection_id: str, + sku_id: str, + *, + inventory_type: InventoryUpdateRequestInventoryType, + update_quantity: typing.Optional[float] = OMIT, + quantity: typing.Optional[float] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[InventoryItem]: + """ + Updates the current inventory levels for a particular SKU item. + + Updates may be given in one or two methods, absolutely or incrementally. + - Absolute updates are done by setting `quantity` directly. + - Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. + + Required scope | `ecommerce:write` + + Parameters + ---------- + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. + + sku_id : str + Unique identifier for a SKU + + inventory_type : InventoryUpdateRequestInventoryType + infinite or finite + + update_quantity : typing.Optional[float] + Adds this quantity to currently store quantity. Can be negative. + + quantity : typing.Optional[float] + Immediately sets quantity to this value. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[InventoryItem] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "inventoryType": inventory_type, + "updateQuantity": update_quantity, + "quantity": quantity, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + InventoryItem, + parse_obj_as( + type_=InventoryItem, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawInventoryClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, sku_collection_id: str, sku_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[InventoryItem]: + """ + List the current inventory levels for a particular SKU item. + + Required scope | `ecommerce:read` + + Parameters + ---------- + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. + + sku_id : str + Unique identifier for a SKU + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[InventoryItem] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + InventoryItem, + parse_obj_as( + type_=InventoryItem, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update( + self, + sku_collection_id: str, + sku_id: str, + *, + inventory_type: InventoryUpdateRequestInventoryType, + update_quantity: typing.Optional[float] = OMIT, + quantity: typing.Optional[float] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[InventoryItem]: + """ + Updates the current inventory levels for a particular SKU item. + + Updates may be given in one or two methods, absolutely or incrementally. + - Absolute updates are done by setting `quantity` directly. + - Incremental updates are by specifying the inventory delta in `updateQuantity` which is then added to the `quantity` stored on the server. + + Required scope | `ecommerce:write` + + Parameters + ---------- + sku_collection_id : str + Unique identifier for a SKU collection. Use the List Collections API to find this ID. + + sku_id : str + Unique identifier for a SKU + + inventory_type : InventoryUpdateRequestInventoryType + infinite or finite + + update_quantity : typing.Optional[float] + Adds this quantity to currently store quantity. Can be negative. + + quantity : typing.Optional[float] + Immediately sets quantity to this value. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[InventoryItem] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"collections/{jsonable_encoder(sku_collection_id)}/items/{jsonable_encoder(sku_id)}/inventory", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "inventoryType": inventory_type, + "updateQuantity": update_quantity, + "quantity": quantity, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + InventoryItem, + parse_obj_as( + type_=InventoryItem, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/inventory/types/__init__.py b/src/webflow/resources/inventory/types/__init__.py index 4cf7822..2cc6148 100644 --- a/src/webflow/resources/inventory/types/__init__.py +++ b/src/webflow/resources/inventory/types/__init__.py @@ -1,6 +1,38 @@ # This file was auto-generated by Fern from our API Definition. -from .ecomm_inventory_changed_payload import EcommInventoryChangedPayload -from .inventory_update_request_inventory_type import InventoryUpdateRequestInventoryType +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .ecomm_inventory_changed_payload import EcommInventoryChangedPayload + from .inventory_update_request_inventory_type import InventoryUpdateRequestInventoryType +_dynamic_imports: typing.Dict[str, str] = { + "EcommInventoryChangedPayload": ".ecomm_inventory_changed_payload", + "InventoryUpdateRequestInventoryType": ".inventory_update_request_inventory_type", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["EcommInventoryChangedPayload", "InventoryUpdateRequestInventoryType"] diff --git a/src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py b/src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py index f4a969e..729740d 100644 --- a/src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py +++ b/src/webflow/resources/inventory/types/ecomm_inventory_changed_payload.py @@ -1,17 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -from ....core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing + +import pydantic +import typing_extensions +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ....core.serialization import FieldMetadata from ....types.inventory_item import InventoryItem -from ....core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class EcommInventoryChangedPayload(UniversalBaseModel): trigger_type: typing_extensions.Annotated[ - typing.Optional[typing.Literal["ecomm_inventory_changed"]], FieldMetadata(alias="triggerType") + typing.Optional[typing.Literal["ecomm_inventory_changed"]], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType"), ] = None payload: typing.Optional[InventoryItem] = None diff --git a/src/webflow/resources/orders/__init__.py b/src/webflow/resources/orders/__init__.py index 7076133..7af8880 100644 --- a/src/webflow/resources/orders/__init__.py +++ b/src/webflow/resources/orders/__init__.py @@ -1,5 +1,34 @@ # This file was auto-generated by Fern from our API Definition. -from .types import OrdersListRequestStatus, OrdersRefundRequestReason +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import OrdersListRequestStatus, OrdersRefundRequestReason +_dynamic_imports: typing.Dict[str, str] = {"OrdersListRequestStatus": ".types", "OrdersRefundRequestReason": ".types"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["OrdersListRequestStatus", "OrdersRefundRequestReason"] diff --git a/src/webflow/resources/orders/client.py b/src/webflow/resources/orders/client.py index b4f39a2..ef55043 100644 --- a/src/webflow/resources/orders/client.py +++ b/src/webflow/resources/orders/client.py @@ -1,25 +1,14 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ...core.client_wrapper import SyncClientWrapper -from .types.orders_list_request_status import OrdersListRequestStatus + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions -from ...types.order_list import OrderList -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.forbidden_error import ForbiddenError -from ...errors.not_found_error import NotFoundError -from ...errors.conflict_error import ConflictError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError from ...types.order import Order +from ...types.order_list import OrderList +from .raw_client import AsyncRawOrdersClient, RawOrdersClient +from .types.orders_list_request_status import OrdersListRequestStatus from .types.orders_refund_request_reason import OrdersRefundRequestReason -from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -27,7 +16,18 @@ class OrdersClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawOrdersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawOrdersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawOrdersClient + """ + return self._raw_client def list( self, @@ -79,100 +79,10 @@ def list( limit=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "status": status, - "offset": offset, - "limit": limit, - }, - request_options=request_options, + _response = self._raw_client.list( + site_id, status=status, offset=offset, limit=limit, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - OrderList, - parse_obj_as( - type_=OrderList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get(self, site_id: str, order_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Order: """ @@ -209,95 +119,8 @@ def get(self, site_id: str, order_id: str, *, request_options: typing.Optional[R order_id="5e8518516e147040726cc415", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Order, - parse_obj_as( - type_=Order, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get(site_id, order_id, request_options=request_options) + return _response.data def update( self, @@ -357,105 +180,16 @@ def update( order_id="5e8518516e147040726cc415", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "comment": comment, - "shippingProvider": shipping_provider, - "shippingTracking": shipping_tracking, - "shippingTrackingURL": shipping_tracking_url, - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.update( + site_id, + order_id, + comment=comment, + shipping_provider=shipping_provider, + shipping_tracking=shipping_tracking, + shipping_tracking_url=shipping_tracking_url, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Order, - parse_obj_as( - type_=Order, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def update_fulfill( self, @@ -501,102 +235,10 @@ def update_fulfill( order_id="5e8518516e147040726cc415", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "sendOrderFulfilledEmail": send_order_fulfilled_email, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.update_fulfill( + site_id, order_id, send_order_fulfilled_email=send_order_fulfilled_email, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Order, - parse_obj_as( - type_=Order, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def update_unfulfill( self, site_id: str, order_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -634,95 +276,8 @@ def update_unfulfill( order_id="5e8518516e147040726cc415", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", - base_url=self._client_wrapper.get_environment().base, - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Order, - parse_obj_as( - type_=Order, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.update_unfulfill(site_id, order_id, request_options=request_options) + return _response.data def refund( self, @@ -769,107 +324,24 @@ def refund( order_id="5e8518516e147040726cc415", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "reason": reason, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Order, - parse_obj_as( - type_=Order, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.refund(site_id, order_id, reason=reason, request_options=request_options) + return _response.data class AsyncOrdersClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawOrdersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawOrdersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawOrdersClient + """ + return self._raw_client async def list( self, @@ -929,100 +401,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "status": status, - "offset": offset, - "limit": limit, - }, - request_options=request_options, + _response = await self._raw_client.list( + site_id, status=status, offset=offset, limit=limit, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - OrderList, - parse_obj_as( - type_=OrderList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get( self, site_id: str, order_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -1069,95 +451,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Order, - parse_obj_as( - type_=Order, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get(site_id, order_id, request_options=request_options) + return _response.data async def update( self, @@ -1225,105 +520,16 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "comment": comment, - "shippingProvider": shipping_provider, - "shippingTracking": shipping_tracking, - "shippingTrackingURL": shipping_tracking_url, - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.update( + site_id, + order_id, + comment=comment, + shipping_provider=shipping_provider, + shipping_tracking=shipping_tracking, + shipping_tracking_url=shipping_tracking_url, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Order, - parse_obj_as( - type_=Order, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def update_fulfill( self, @@ -1377,102 +583,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "sendOrderFulfilledEmail": send_order_fulfilled_email, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.update_fulfill( + site_id, order_id, send_order_fulfilled_email=send_order_fulfilled_email, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Order, - parse_obj_as( - type_=Order, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def update_unfulfill( self, site_id: str, order_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -1518,95 +632,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", - base_url=self._client_wrapper.get_environment().base, - method="POST", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Order, - parse_obj_as( - type_=Order, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.update_unfulfill(site_id, order_id, request_options=request_options) + return _response.data async def refund( self, @@ -1661,99 +688,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "reason": reason, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Order, - parse_obj_as( - type_=Order, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.refund(site_id, order_id, reason=reason, request_options=request_options) + return _response.data diff --git a/src/webflow/resources/orders/raw_client.py b/src/webflow/resources/orders/raw_client.py new file mode 100644 index 0000000..be3cd04 --- /dev/null +++ b/src/webflow/resources/orders/raw_client.py @@ -0,0 +1,1712 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...errors.bad_request_error import BadRequestError +from ...errors.conflict_error import ConflictError +from ...errors.forbidden_error import ForbiddenError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error +from ...types.order import Order +from ...types.order_list import OrderList +from .types.orders_list_request_status import OrdersListRequestStatus +from .types.orders_refund_request_reason import OrdersRefundRequestReason +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawOrdersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + site_id: str, + *, + status: typing.Optional[OrdersListRequestStatus] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[OrderList]: + """ + List all orders created for a given site. + + Required scope | `ecommerce:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + status : typing.Optional[OrdersListRequestStatus] + Filter the orders by status + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[OrderList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "status": status, + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + OrderList, + parse_obj_as( + type_=OrderList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get( + self, site_id: str, order_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[Order]: + """ + Retrieve a single product by its ID. All of its SKUs will also be + retrieved. + + Required scope | `ecommerce:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Order] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update( + self, + site_id: str, + order_id: str, + *, + comment: typing.Optional[str] = OMIT, + shipping_provider: typing.Optional[str] = OMIT, + shipping_tracking: typing.Optional[str] = OMIT, + shipping_tracking_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Order]: + """ + This API lets you update the fields, `comment`, `shippingProvider`, + and/or `shippingTracking` for a given order. All three fields can be + updated simultaneously or independently. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + comment : typing.Optional[str] + Arbitrary data for your records + + shipping_provider : typing.Optional[str] + Company or method used to ship order + + shipping_tracking : typing.Optional[str] + Tracking number for order shipment + + shipping_tracking_url : typing.Optional[str] + URL to track order shipment + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Order] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "comment": comment, + "shippingProvider": shipping_provider, + "shippingTracking": shipping_tracking, + "shippingTrackingURL": shipping_tracking_url, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_fulfill( + self, + site_id: str, + order_id: str, + *, + send_order_fulfilled_email: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Order]: + """ + Updates an order's status to fulfilled + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + send_order_fulfilled_email : typing.Optional[bool] + Whether or not the Order Fulfilled email should be sent + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Order] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "sendOrderFulfilledEmail": send_order_fulfilled_email, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_unfulfill( + self, site_id: str, order_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[Order]: + """ + Updates an order's status to unfulfilled + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Order] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", + base_url=self._client_wrapper.get_environment().base, + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def refund( + self, + site_id: str, + order_id: str, + *, + reason: typing.Optional[OrdersRefundRequestReason] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Order]: + """ + This API will reverse a Stripe charge and refund an order back to a + customer. It will also set the order's status to `refunded`. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + reason : typing.Optional[OrdersRefundRequestReason] + The reason for the refund + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Order] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "reason": reason, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawOrdersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + site_id: str, + *, + status: typing.Optional[OrdersListRequestStatus] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[OrderList]: + """ + List all orders created for a given site. + + Required scope | `ecommerce:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + status : typing.Optional[OrdersListRequestStatus] + Filter the orders by status + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[OrderList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "status": status, + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + OrderList, + parse_obj_as( + type_=OrderList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get( + self, site_id: str, order_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Order]: + """ + Retrieve a single product by its ID. All of its SKUs will also be + retrieved. + + Required scope | `ecommerce:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Order] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update( + self, + site_id: str, + order_id: str, + *, + comment: typing.Optional[str] = OMIT, + shipping_provider: typing.Optional[str] = OMIT, + shipping_tracking: typing.Optional[str] = OMIT, + shipping_tracking_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Order]: + """ + This API lets you update the fields, `comment`, `shippingProvider`, + and/or `shippingTracking` for a given order. All three fields can be + updated simultaneously or independently. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + comment : typing.Optional[str] + Arbitrary data for your records + + shipping_provider : typing.Optional[str] + Company or method used to ship order + + shipping_tracking : typing.Optional[str] + Tracking number for order shipment + + shipping_tracking_url : typing.Optional[str] + URL to track order shipment + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Order] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "comment": comment, + "shippingProvider": shipping_provider, + "shippingTracking": shipping_tracking, + "shippingTrackingURL": shipping_tracking_url, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_fulfill( + self, + site_id: str, + order_id: str, + *, + send_order_fulfilled_email: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Order]: + """ + Updates an order's status to fulfilled + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + send_order_fulfilled_email : typing.Optional[bool] + Whether or not the Order Fulfilled email should be sent + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Order] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/fulfill", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "sendOrderFulfilledEmail": send_order_fulfilled_email, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_unfulfill( + self, site_id: str, order_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Order]: + """ + Updates an order's status to unfulfilled + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Order] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/unfulfill", + base_url=self._client_wrapper.get_environment().base, + method="POST", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def refund( + self, + site_id: str, + order_id: str, + *, + reason: typing.Optional[OrdersRefundRequestReason] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Order]: + """ + This API will reverse a Stripe charge and refund an order back to a + customer. It will also set the order's status to `refunded`. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + order_id : str + Unique identifier for an Order + + reason : typing.Optional[OrdersRefundRequestReason] + The reason for the refund + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Order] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/orders/{jsonable_encoder(order_id)}/refund", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "reason": reason, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Order, + parse_obj_as( + type_=Order, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/orders/types/__init__.py b/src/webflow/resources/orders/types/__init__.py index 7df0fa1..d06e415 100644 --- a/src/webflow/resources/orders/types/__init__.py +++ b/src/webflow/resources/orders/types/__init__.py @@ -1,6 +1,38 @@ # This file was auto-generated by Fern from our API Definition. -from .orders_list_request_status import OrdersListRequestStatus -from .orders_refund_request_reason import OrdersRefundRequestReason +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .orders_list_request_status import OrdersListRequestStatus + from .orders_refund_request_reason import OrdersRefundRequestReason +_dynamic_imports: typing.Dict[str, str] = { + "OrdersListRequestStatus": ".orders_list_request_status", + "OrdersRefundRequestReason": ".orders_refund_request_reason", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["OrdersListRequestStatus", "OrdersRefundRequestReason"] diff --git a/src/webflow/resources/pages/__init__.py b/src/webflow/resources/pages/__init__.py index 898d3de..25684a4 100644 --- a/src/webflow/resources/pages/__init__.py +++ b/src/webflow/resources/pages/__init__.py @@ -1,7 +1,47 @@ # This file was auto-generated by Fern from our API Definition. -from .types import PageDomWriteNodesItem, PageMetadataWriteOpenGraph, PageMetadataWriteSeo, UpdateStaticContentResponse -from .resources import scripts +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import ( + PageDomWriteNodesItem, + PageMetadataWriteOpenGraph, + PageMetadataWriteSeo, + UpdateStaticContentResponse, + ) + from .resources import scripts +_dynamic_imports: typing.Dict[str, str] = { + "PageDomWriteNodesItem": ".types", + "PageMetadataWriteOpenGraph": ".types", + "PageMetadataWriteSeo": ".types", + "UpdateStaticContentResponse": ".types", + "scripts": ".resources", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "PageDomWriteNodesItem", diff --git a/src/webflow/resources/pages/client.py b/src/webflow/resources/pages/client.py index fb5fe60..9f6f980 100644 --- a/src/webflow/resources/pages/client.py +++ b/src/webflow/resources/pages/client.py @@ -1,39 +1,42 @@ # This file was auto-generated by Fern from our API Definition. +from __future__ import annotations + import typing -from ...core.client_wrapper import SyncClientWrapper -from .resources.scripts.client import ScriptsClient + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions -from ...types.page_list import PageList -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.not_found_error import NotFoundError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from ...types.page import Page -from .types.page_metadata_write_seo import PageMetadataWriteSeo -from .types.page_metadata_write_open_graph import PageMetadataWriteOpenGraph -from ...core.serialization import convert_and_respect_annotation_metadata from ...types.dom import Dom -from ...errors.forbidden_error import ForbiddenError +from ...types.page import Page +from ...types.page_list import PageList +from .raw_client import AsyncRawPagesClient, RawPagesClient from .types.page_dom_write_nodes_item import PageDomWriteNodesItem +from .types.page_metadata_write_open_graph import PageMetadataWriteOpenGraph +from .types.page_metadata_write_seo import PageMetadataWriteSeo from .types.update_static_content_response import UpdateStaticContentResponse -from ...core.client_wrapper import AsyncClientWrapper -from .resources.scripts.client import AsyncScriptsClient +if typing.TYPE_CHECKING: + from .resources.scripts.client import AsyncScriptsClient, ScriptsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) class PagesClient: def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawPagesClient(client_wrapper=client_wrapper) self._client_wrapper = client_wrapper - self.scripts = ScriptsClient(client_wrapper=self._client_wrapper) + self._scripts: typing.Optional[ScriptsClient] = None + + @property + def with_raw_response(self) -> RawPagesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawPagesClient + """ + return self._raw_client def list( self, @@ -87,80 +90,10 @@ def list( offset=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/pages", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "limit": limit, - "offset": offset, - }, - request_options=request_options, + _response = self._raw_client.list( + site_id, locale_id=locale_id, limit=limit, offset=offset, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - PageList, - parse_obj_as( - type_=PageList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get_metadata( self, @@ -204,78 +137,8 @@ def get_metadata( locale_id="65427cf400e02b306eaa04a0", ) """ - _response = self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Page, - parse_obj_as( - type_=Page, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get_metadata(page_id, locale_id=locale_id, request_options=request_options) + return _response.data def update_page_settings( self, @@ -354,92 +217,16 @@ def update_page_settings( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PUT", - params={ - "localeId": locale_id, - }, - json={ - "title": title, - "slug": slug, - "seo": convert_and_respect_annotation_metadata( - object_=seo, annotation=PageMetadataWriteSeo, direction="write" - ), - "openGraph": convert_and_respect_annotation_metadata( - object_=open_graph, annotation=PageMetadataWriteOpenGraph, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.update_page_settings( + page_id, + locale_id=locale_id, + title=title, + slug=slug, + seo=seo, + open_graph=open_graph, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Page, - parse_obj_as( - type_=Page, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get_content( self, @@ -495,90 +282,10 @@ def get_content( offset=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/dom", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "limit": limit, - "offset": offset, - }, - request_options=request_options, + _response = self._raw_client.get_content( + page_id, locale_id=locale_id, limit=limit, offset=offset, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Dom, - parse_obj_as( - type_=Dom, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def update_static_content( self, @@ -687,103 +394,36 @@ def update_static_content( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/dom", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "localeId": locale_id, - }, - json={ - "nodes": convert_and_respect_annotation_metadata( - object_=nodes, annotation=typing.Sequence[PageDomWriteNodesItem], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.update_static_content( + page_id, locale_id=locale_id, nodes=nodes, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - UpdateStaticContentResponse, - parse_obj_as( - type_=UpdateStaticContentResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data + + @property + def scripts(self): + if self._scripts is None: + from .resources.scripts.client import ScriptsClient # noqa: E402 + + self._scripts = ScriptsClient(client_wrapper=self._client_wrapper) + return self._scripts class AsyncPagesClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawPagesClient(client_wrapper=client_wrapper) self._client_wrapper = client_wrapper - self.scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) + self._scripts: typing.Optional[AsyncScriptsClient] = None + + @property + def with_raw_response(self) -> AsyncRawPagesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawPagesClient + """ + return self._raw_client async def list( self, @@ -845,80 +485,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/pages", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "limit": limit, - "offset": offset, - }, - request_options=request_options, + _response = await self._raw_client.list( + site_id, locale_id=locale_id, limit=limit, offset=offset, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - PageList, - parse_obj_as( - type_=PageList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get_metadata( self, @@ -970,78 +540,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Page, - parse_obj_as( - type_=Page, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get_metadata(page_id, locale_id=locale_id, request_options=request_options) + return _response.data async def update_page_settings( self, @@ -1128,92 +628,16 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PUT", - params={ - "localeId": locale_id, - }, - json={ - "title": title, - "slug": slug, - "seo": convert_and_respect_annotation_metadata( - object_=seo, annotation=PageMetadataWriteSeo, direction="write" - ), - "openGraph": convert_and_respect_annotation_metadata( - object_=open_graph, annotation=PageMetadataWriteOpenGraph, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.update_page_settings( + page_id, + locale_id=locale_id, + title=title, + slug=slug, + seo=seo, + open_graph=open_graph, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Page, - parse_obj_as( - type_=Page, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get_content( self, @@ -1277,90 +701,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/dom", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "limit": limit, - "offset": offset, - }, - request_options=request_options, + _response = await self._raw_client.get_content( + page_id, locale_id=locale_id, limit=limit, offset=offset, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Dom, - parse_obj_as( - type_=Dom, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def update_static_content( self, @@ -1477,94 +821,15 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/dom", - base_url=self._client_wrapper.get_environment().base, - method="POST", - params={ - "localeId": locale_id, - }, - json={ - "nodes": convert_and_respect_annotation_metadata( - object_=nodes, annotation=typing.Sequence[PageDomWriteNodesItem], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.update_static_content( + page_id, locale_id=locale_id, nodes=nodes, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - UpdateStaticContentResponse, - parse_obj_as( - type_=UpdateStaticContentResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data + + @property + def scripts(self): + if self._scripts is None: + from .resources.scripts.client import AsyncScriptsClient # noqa: E402 + + self._scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) + return self._scripts diff --git a/src/webflow/resources/pages/raw_client.py b/src/webflow/resources/pages/raw_client.py new file mode 100644 index 0000000..1287d92 --- /dev/null +++ b/src/webflow/resources/pages/raw_client.py @@ -0,0 +1,1365 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...core.serialization import convert_and_respect_annotation_metadata +from ...errors.bad_request_error import BadRequestError +from ...errors.forbidden_error import ForbiddenError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.dom import Dom +from ...types.error import Error +from ...types.page import Page +from ...types.page_list import PageList +from .types.page_dom_write_nodes_item import PageDomWriteNodesItem +from .types.page_metadata_write_open_graph import PageMetadataWriteOpenGraph +from .types.page_metadata_write_seo import PageMetadataWriteSeo +from .types.update_static_content_response import UpdateStaticContentResponse +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawPagesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + site_id: str, + *, + locale_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[PageList]: + """ + List of all pages for a site. + + Required scope | `pages:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[PageList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/pages", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + PageList, + parse_obj_as( + type_=PageList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_metadata( + self, + page_id: str, + *, + locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Page]: + """ + Get metadata information for a single page. + + Required scope | `pages:read` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Page] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Page, + parse_obj_as( + type_=Page, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_page_settings( + self, + page_id: str, + *, + locale_id: typing.Optional[str] = None, + title: typing.Optional[str] = OMIT, + slug: typing.Optional[str] = OMIT, + seo: typing.Optional[PageMetadataWriteSeo] = OMIT, + open_graph: typing.Optional[PageMetadataWriteOpenGraph] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Page]: + """ + Update Page-level metadata, including SEO and Open Graph fields. + + Required scope | `pages:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + title : typing.Optional[str] + Title for the page + + slug : typing.Optional[str] + Slug for the page. + + + **Note:** Updating slugs in secondary locales is only supported in Advanced and Enterprise localization add-on plans. + + seo : typing.Optional[PageMetadataWriteSeo] + SEO-related fields for the Page + + open_graph : typing.Optional[PageMetadataWriteOpenGraph] + Open Graph fields for the Page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Page] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + params={ + "localeId": locale_id, + }, + json={ + "title": title, + "slug": slug, + "seo": convert_and_respect_annotation_metadata( + object_=seo, annotation=PageMetadataWriteSeo, direction="write" + ), + "openGraph": convert_and_respect_annotation_metadata( + object_=open_graph, annotation=PageMetadataWriteOpenGraph, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Page, + parse_obj_as( + type_=Page, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_content( + self, + page_id: str, + *, + locale_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Dom]: + """ + Get text and component instance content from a static page. + + Localization + + Required scope | `pages:read` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Dom] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Dom, + parse_obj_as( + type_=Dom, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_static_content( + self, + page_id: str, + *, + locale_id: str, + nodes: typing.Sequence[PageDomWriteNodesItem], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[UpdateStaticContentResponse]: + """ + This endpoint updates content on a static page in **secondary locales**. It supports updating up to 1000 nodes in a single request. + + Before making updates: + 1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) endpoint to identify available content nodes and their types. + 2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + 3. DOM elements may include a `data-w-id` attribute. This attribute is used by Webflow to maintain custom attributes and links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. + + + This endpoint is specifically for localized pages. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + + Required scope | `pages:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale_id : str + The locale identifier. + + nodes : typing.Sequence[PageDomWriteNodesItem] + List of DOM Nodes with the new content that will be updated in each node. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[UpdateStaticContentResponse] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "localeId": locale_id, + }, + json={ + "nodes": convert_and_respect_annotation_metadata( + object_=nodes, annotation=typing.Sequence[PageDomWriteNodesItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + UpdateStaticContentResponse, + parse_obj_as( + type_=UpdateStaticContentResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawPagesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + site_id: str, + *, + locale_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[PageList]: + """ + List of all pages for a site. + + Required scope | `pages:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[PageList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/pages", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + PageList, + parse_obj_as( + type_=PageList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_metadata( + self, + page_id: str, + *, + locale_id: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Page]: + """ + Get metadata information for a single page. + + Required scope | `pages:read` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Page] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Page, + parse_obj_as( + type_=Page, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_page_settings( + self, + page_id: str, + *, + locale_id: typing.Optional[str] = None, + title: typing.Optional[str] = OMIT, + slug: typing.Optional[str] = OMIT, + seo: typing.Optional[PageMetadataWriteSeo] = OMIT, + open_graph: typing.Optional[PageMetadataWriteOpenGraph] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Page]: + """ + Update Page-level metadata, including SEO and Open Graph fields. + + Required scope | `pages:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + title : typing.Optional[str] + Title for the page + + slug : typing.Optional[str] + Slug for the page. + + + **Note:** Updating slugs in secondary locales is only supported in Advanced and Enterprise localization add-on plans. + + seo : typing.Optional[PageMetadataWriteSeo] + SEO-related fields for the Page + + open_graph : typing.Optional[PageMetadataWriteOpenGraph] + Open Graph fields for the Page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Page] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + params={ + "localeId": locale_id, + }, + json={ + "title": title, + "slug": slug, + "seo": convert_and_respect_annotation_metadata( + object_=seo, annotation=PageMetadataWriteSeo, direction="write" + ), + "openGraph": convert_and_respect_annotation_metadata( + object_=open_graph, annotation=PageMetadataWriteOpenGraph, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Page, + parse_obj_as( + type_=Page, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_content( + self, + page_id: str, + *, + locale_id: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Dom]: + """ + Get text and component instance content from a static page. + + Localization + + Required scope | `pages:read` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Dom] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Dom, + parse_obj_as( + type_=Dom, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_static_content( + self, + page_id: str, + *, + locale_id: str, + nodes: typing.Sequence[PageDomWriteNodesItem], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[UpdateStaticContentResponse]: + """ + This endpoint updates content on a static page in **secondary locales**. It supports updating up to 1000 nodes in a single request. + + Before making updates: + 1. Use the [get page content](/data/reference/pages-and-components/pages/get-content) endpoint to identify available content nodes and their types. + 2. If the page has component instances, retrieve the component's properties that you'll override using the [get component properties](/data/reference/pages-and-components/components/get-properties) endpoint. + 3. DOM elements may include a `data-w-id` attribute. This attribute is used by Webflow to maintain custom attributes and links across locales. Always include the original `data-w-id` value in your update requests to ensure consistent behavior across all locales. + + + This endpoint is specifically for localized pages. Ensure that the specified `localeId` is a valid **secondary locale** for the site otherwise the request will fail. + + + Required scope | `pages:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + locale_id : str + The locale identifier. + + nodes : typing.Sequence[PageDomWriteNodesItem] + List of DOM Nodes with the new content that will be updated in each node. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[UpdateStaticContentResponse] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}/dom", + base_url=self._client_wrapper.get_environment().base, + method="POST", + params={ + "localeId": locale_id, + }, + json={ + "nodes": convert_and_respect_annotation_metadata( + object_=nodes, annotation=typing.Sequence[PageDomWriteNodesItem], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + UpdateStaticContentResponse, + parse_obj_as( + type_=UpdateStaticContentResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/pages/resources/__init__.py b/src/webflow/resources/pages/resources/__init__.py index 58b2c01..14bbc78 100644 --- a/src/webflow/resources/pages/resources/__init__.py +++ b/src/webflow/resources/pages/resources/__init__.py @@ -1,5 +1,34 @@ # This file was auto-generated by Fern from our API Definition. -from . import scripts +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from . import scripts +_dynamic_imports: typing.Dict[str, str] = {"scripts": ".scripts"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["scripts"] diff --git a/src/webflow/resources/pages/resources/scripts/__init__.py b/src/webflow/resources/pages/resources/scripts/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/pages/resources/scripts/__init__.py +++ b/src/webflow/resources/pages/resources/scripts/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/pages/resources/scripts/client.py b/src/webflow/resources/pages/resources/scripts/client.py index cd1086f..205dca5 100644 --- a/src/webflow/resources/pages/resources/scripts/client.py +++ b/src/webflow/resources/pages/resources/scripts/client.py @@ -1,23 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -from .....core.client_wrapper import SyncClientWrapper + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions -from .....types.script_apply_list import ScriptApplyList -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as -from .....errors.bad_request_error import BadRequestError -from .....errors.unauthorized_error import UnauthorizedError -from .....types.error import Error -from .....errors.not_found_error import NotFoundError -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError from .....types.script_apply import ScriptApply -from .....core.serialization import convert_and_respect_annotation_metadata -from .....errors.conflict_error import ConflictError -from .....core.client_wrapper import AsyncClientWrapper +from .....types.script_apply_list import ScriptApplyList +from .raw_client import AsyncRawScriptsClient, RawScriptsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -25,7 +14,18 @@ class ScriptsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawScriptsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawScriptsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawScriptsClient + """ + return self._raw_client def get_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -59,75 +59,8 @@ def get_custom_code( page_id="63c720f9347c2139b248e552", ) """ - _response = self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ScriptApplyList, - parse_obj_as( - type_=ScriptApplyList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get_custom_code(page_id, request_options=request_options) + return _response.data def upsert_custom_code( self, @@ -193,93 +126,10 @@ def upsert_custom_code( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="PUT", - json={ - "scripts": convert_and_respect_annotation_metadata( - object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" - ), - "lastUpdated": last_updated, - "createdOn": created_on, - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.upsert_custom_code( + page_id, scripts=scripts, last_updated=last_updated, created_on=created_on, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ScriptApplyList, - parse_obj_as( - type_=ScriptApplyList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def delete_custom_code(self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ @@ -314,74 +164,24 @@ def delete_custom_code(self, page_id: str, *, request_options: typing.Optional[R page_id="63c720f9347c2139b248e552", ) """ - _response = self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete_custom_code(page_id, request_options=request_options) + return _response.data class AsyncScriptsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawScriptsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawScriptsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawScriptsClient + """ + return self._raw_client async def get_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -423,75 +223,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ScriptApplyList, - parse_obj_as( - type_=ScriptApplyList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get_custom_code(page_id, request_options=request_options) + return _response.data async def upsert_custom_code( self, @@ -565,93 +298,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="PUT", - json={ - "scripts": convert_and_respect_annotation_metadata( - object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" - ), - "lastUpdated": last_updated, - "createdOn": created_on, - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.upsert_custom_code( + page_id, scripts=scripts, last_updated=last_updated, created_on=created_on, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ScriptApplyList, - parse_obj_as( - type_=ScriptApplyList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def delete_custom_code( self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -696,66 +346,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"pages/{jsonable_encoder(page_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.delete_custom_code(page_id, request_options=request_options) + return _response.data diff --git a/src/webflow/resources/pages/resources/scripts/raw_client.py b/src/webflow/resources/pages/resources/scripts/raw_client.py new file mode 100644 index 0000000..6a71dd8 --- /dev/null +++ b/src/webflow/resources/pages/resources/scripts/raw_client.py @@ -0,0 +1,716 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....core.serialization import convert_and_respect_annotation_metadata +from .....errors.bad_request_error import BadRequestError +from .....errors.conflict_error import ConflictError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....types.script_apply import ScriptApply +from .....types.script_apply_list import ScriptApplyList +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawScriptsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_custom_code( + self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[ScriptApplyList]: + """ + Get all scripts applied to a page. + + Required scope | `custom_code:read` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ScriptApplyList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def upsert_custom_code( + self, + page_id: str, + *, + scripts: typing.Optional[typing.Sequence[ScriptApply]] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ScriptApplyList]: + """ + Apply registered scripts to a page. If you have multiple scripts your App needs to apply or maintain on a page, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. + + + To apply a script to a page, the script must first be registered to a Site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + scripts : typing.Optional[typing.Sequence[ScriptApply]] + A list of scripts applied to a Site or a Page + + last_updated : typing.Optional[str] + Date when the Site's scripts were last updated + + created_on : typing.Optional[str] + Date when the Site's scripts were created + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ScriptApplyList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "scripts": convert_and_respect_annotation_metadata( + object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" + ), + "lastUpdated": last_updated, + "createdOn": created_on, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete_custom_code( + self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + Remove all scripts from a page applied by the App. This endpoint will not remove scripts from the site's registered scripts. + + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-pages/upsert-custom-code) endpoint. + + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). + + Required scope | `custom_code:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawScriptsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_custom_code( + self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[ScriptApplyList]: + """ + Get all scripts applied to a page. + + Required scope | `custom_code:read` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ScriptApplyList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def upsert_custom_code( + self, + page_id: str, + *, + scripts: typing.Optional[typing.Sequence[ScriptApply]] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ScriptApplyList]: + """ + Apply registered scripts to a page. If you have multiple scripts your App needs to apply or maintain on a page, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. + + + To apply a script to a page, the script must first be registered to a Site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + scripts : typing.Optional[typing.Sequence[ScriptApply]] + A list of scripts applied to a Site or a Page + + last_updated : typing.Optional[str] + Date when the Site's scripts were last updated + + created_on : typing.Optional[str] + Date when the Site's scripts were created + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ScriptApplyList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "scripts": convert_and_respect_annotation_metadata( + object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" + ), + "lastUpdated": last_updated, + "createdOn": created_on, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete_custom_code( + self, page_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Remove all scripts from a page applied by the App. This endpoint will not remove scripts from the site's registered scripts. + + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-pages/upsert-custom-code) endpoint. + + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). + + Required scope | `custom_code:write` + + Parameters + ---------- + page_id : str + Unique identifier for a Page + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"pages/{jsonable_encoder(page_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/pages/types/__init__.py b/src/webflow/resources/pages/types/__init__.py index 6e07bcf..e606a89 100644 --- a/src/webflow/resources/pages/types/__init__.py +++ b/src/webflow/resources/pages/types/__init__.py @@ -1,8 +1,42 @@ # This file was auto-generated by Fern from our API Definition. -from .page_dom_write_nodes_item import PageDomWriteNodesItem -from .page_metadata_write_open_graph import PageMetadataWriteOpenGraph -from .page_metadata_write_seo import PageMetadataWriteSeo -from .update_static_content_response import UpdateStaticContentResponse +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .page_dom_write_nodes_item import PageDomWriteNodesItem + from .page_metadata_write_open_graph import PageMetadataWriteOpenGraph + from .page_metadata_write_seo import PageMetadataWriteSeo + from .update_static_content_response import UpdateStaticContentResponse +_dynamic_imports: typing.Dict[str, str] = { + "PageDomWriteNodesItem": ".page_dom_write_nodes_item", + "PageMetadataWriteOpenGraph": ".page_metadata_write_open_graph", + "PageMetadataWriteSeo": ".page_metadata_write_seo", + "UpdateStaticContentResponse": ".update_static_content_response", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["PageDomWriteNodesItem", "PageMetadataWriteOpenGraph", "PageMetadataWriteSeo", "UpdateStaticContentResponse"] diff --git a/src/webflow/resources/pages/types/page_dom_write_nodes_item.py b/src/webflow/resources/pages/types/page_dom_write_nodes_item.py index 7c616d9..8c562cf 100644 --- a/src/webflow/resources/pages/types/page_dom_write_nodes_item.py +++ b/src/webflow/resources/pages/types/page_dom_write_nodes_item.py @@ -1,12 +1,13 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ....types.text_node_write import TextNodeWrite + from ....types.component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite +from ....types.search_button_node_write import SearchButtonNodeWrite from ....types.select import Select -from ....types.text_input_node_write import TextInputNodeWrite from ....types.submit_button_node_write import SubmitButtonNodeWrite -from ....types.search_button_node_write import SearchButtonNodeWrite +from ....types.text_input_node_write import TextInputNodeWrite +from ....types.text_node_write import TextNodeWrite PageDomWriteNodesItem = typing.Union[ TextNodeWrite, diff --git a/src/webflow/resources/pages/types/page_metadata_write_open_graph.py b/src/webflow/resources/pages/types/page_metadata_write_open_graph.py index 7b6a099..0a80301 100644 --- a/src/webflow/resources/pages/types/page_metadata_write_open_graph.py +++ b/src/webflow/resources/pages/types/page_metadata_write_open_graph.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ....core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ....core.serialization import FieldMetadata -from ....core.pydantic_utilities import IS_PYDANTIC_V2 class PageMetadataWriteOpenGraph(UniversalBaseModel): @@ -18,24 +18,24 @@ class PageMetadataWriteOpenGraph(UniversalBaseModel): The title supplied to Open Graph annotations """ - title_copied: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="titleCopied")] = ( - pydantic.Field(default=None) - ) - """ - Indicates the Open Graph title was copied from the SEO title - """ - + title_copied: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="titleCopied"), + pydantic.Field(alias="titleCopied", description="Indicates the Open Graph title was copied from the SEO title"), + ] = None description: typing.Optional[str] = pydantic.Field(default=None) """ The description supplied to Open Graph annotations """ - description_copied: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="descriptionCopied")] = ( - pydantic.Field(default=None) - ) - """ - Indicates the Open Graph description was copied from the SEO description - """ + description_copied: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="descriptionCopied"), + pydantic.Field( + alias="descriptionCopied", + description="Indicates the Open Graph description was copied from the SEO description", + ), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/resources/pages/types/page_metadata_write_seo.py b/src/webflow/resources/pages/types/page_metadata_write_seo.py index 1b339a0..a03a778 100644 --- a/src/webflow/resources/pages/types/page_metadata_write_seo.py +++ b/src/webflow/resources/pages/types/page_metadata_write_seo.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ....core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class PageMetadataWriteSeo(UniversalBaseModel): diff --git a/src/webflow/resources/pages/types/update_static_content_response.py b/src/webflow/resources/pages/types/update_static_content_response.py index 0bcf93a..99e93aa 100644 --- a/src/webflow/resources/pages/types/update_static_content_response.py +++ b/src/webflow/resources/pages/types/update_static_content_response.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ....core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2 +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class UpdateStaticContentResponse(UniversalBaseModel): diff --git a/src/webflow/resources/products/__init__.py b/src/webflow/resources/products/__init__.py index adf933b..fe1618a 100644 --- a/src/webflow/resources/products/__init__.py +++ b/src/webflow/resources/products/__init__.py @@ -1,5 +1,38 @@ # This file was auto-generated by Fern from our API Definition. -from .types import ProductSkuCreateProduct, ProductSkuCreateSku, ProductsCreateSkuResponse +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import ProductSkuCreateProduct, ProductSkuCreateSku, ProductsCreateSkuResponse +_dynamic_imports: typing.Dict[str, str] = { + "ProductSkuCreateProduct": ".types", + "ProductSkuCreateSku": ".types", + "ProductsCreateSkuResponse": ".types", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["ProductSkuCreateProduct", "ProductSkuCreateSku", "ProductsCreateSkuResponse"] diff --git a/src/webflow/resources/products/client.py b/src/webflow/resources/products/client.py index 5850318..c20d5cf 100644 --- a/src/webflow/resources/products/client.py +++ b/src/webflow/resources/products/client.py @@ -1,30 +1,18 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ...core.client_wrapper import SyncClientWrapper + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.product import Product +from ...types.product_and_sk_us import ProductAndSkUs from ...types.product_and_sk_us_list import ProductAndSkUsList -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.forbidden_error import ForbiddenError -from ...errors.not_found_error import NotFoundError -from ...errors.conflict_error import ConflictError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError -from .types.product_sku_create_product import ProductSkuCreateProduct -from .types.product_sku_create_sku import ProductSkuCreateSku from ...types.publish_status import PublishStatus -from ...types.product_and_sk_us import ProductAndSkUs -from ...core.serialization import convert_and_respect_annotation_metadata -from ...types.product import Product from ...types.sku import Sku +from .raw_client import AsyncRawProductsClient, RawProductsClient +from .types.product_sku_create_product import ProductSkuCreateProduct +from .types.product_sku_create_sku import ProductSkuCreateSku from .types.products_create_sku_response import ProductsCreateSkuResponse -from ...core.client_wrapper import AsyncClientWrapper # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -32,7 +20,18 @@ class ProductsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawProductsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawProductsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawProductsClient + """ + return self._raw_client def list( self, @@ -82,99 +81,8 @@ def list( limit=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "offset": offset, - "limit": limit, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ProductAndSkUsList, - parse_obj_as( - type_=ProductAndSkUsList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.list(site_id, offset=offset, limit=limit, request_options=request_options) + return _response.data def create( self, @@ -302,108 +210,10 @@ def create( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "publishStatus": publish_status, - "product": convert_and_respect_annotation_metadata( - object_=product, annotation=ProductSkuCreateProduct, direction="write" - ), - "sku": convert_and_respect_annotation_metadata( - object_=sku, annotation=ProductSkuCreateSku, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.create( + site_id, product=product, sku=sku, publish_status=publish_status, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ProductAndSkUs, - parse_obj_as( - type_=ProductAndSkUs, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get( self, site_id: str, product_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -442,95 +252,8 @@ def get( product_id="580e63fc8c9a982ac9b8b745", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ProductAndSkUs, - parse_obj_as( - type_=ProductAndSkUs, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get(site_id, product_id, request_options=request_options) + return _response.data def update( self, @@ -583,106 +306,15 @@ def update( product_id="580e63fc8c9a982ac9b8b745", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "publishStatus": publish_status, - "product": convert_and_respect_annotation_metadata( - object_=product, annotation=Product, direction="write" - ), - "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.update( + site_id, + product_id, + publish_status=publish_status, + product=product, + sku=sku, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Product, - parse_obj_as( - type_=Product, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def create_sku( self, @@ -759,105 +391,10 @@ def create_sku( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "publishStatus": publish_status, - "skus": convert_and_respect_annotation_metadata( - object_=skus, annotation=typing.Sequence[Sku], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.create_sku( + site_id, product_id, skus=skus, publish_status=publish_status, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ProductsCreateSkuResponse, - parse_obj_as( - type_=ProductsCreateSkuResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def update_sku( self, @@ -936,108 +473,26 @@ def update_sku( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "publishStatus": publish_status, - "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.update_sku( + site_id, product_id, sku_id, sku=sku, publish_status=publish_status, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Sku, - parse_obj_as( - type_=Sku, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data class AsyncProductsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawProductsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawProductsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawProductsClient + """ + return self._raw_client async def list( self, @@ -1095,99 +550,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "offset": offset, - "limit": limit, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ProductAndSkUsList, - parse_obj_as( - type_=ProductAndSkUsList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.list(site_id, offset=offset, limit=limit, request_options=request_options) + return _response.data async def create( self, @@ -1323,108 +687,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "publishStatus": publish_status, - "product": convert_and_respect_annotation_metadata( - object_=product, annotation=ProductSkuCreateProduct, direction="write" - ), - "sku": convert_and_respect_annotation_metadata( - object_=sku, annotation=ProductSkuCreateSku, direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.create( + site_id, product=product, sku=sku, publish_status=publish_status, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ProductAndSkUs, - parse_obj_as( - type_=ProductAndSkUs, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get( self, site_id: str, product_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -1471,95 +737,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ProductAndSkUs, - parse_obj_as( - type_=ProductAndSkUs, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get(site_id, product_id, request_options=request_options) + return _response.data async def update( self, @@ -1620,106 +799,15 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "publishStatus": publish_status, - "product": convert_and_respect_annotation_metadata( - object_=product, annotation=Product, direction="write" - ), - "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.update( + site_id, + product_id, + publish_status=publish_status, + product=product, + sku=sku, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Product, - parse_obj_as( - type_=Product, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def create_sku( self, @@ -1803,105 +891,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "publishStatus": publish_status, - "skus": convert_and_respect_annotation_metadata( - object_=skus, annotation=typing.Sequence[Sku], direction="write" - ), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.create_sku( + site_id, product_id, skus=skus, publish_status=publish_status, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ProductsCreateSkuResponse, - parse_obj_as( - type_=ProductsCreateSkuResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def update_sku( self, @@ -1987,100 +980,7 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "publishStatus": publish_status, - "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.update_sku( + site_id, product_id, sku_id, sku=sku, publish_status=publish_status, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Sku, - parse_obj_as( - type_=Sku, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data diff --git a/src/webflow/resources/products/raw_client.py b/src/webflow/resources/products/raw_client.py new file mode 100644 index 0000000..e7b0965 --- /dev/null +++ b/src/webflow/resources/products/raw_client.py @@ -0,0 +1,1791 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...core.serialization import convert_and_respect_annotation_metadata +from ...errors.bad_request_error import BadRequestError +from ...errors.conflict_error import ConflictError +from ...errors.forbidden_error import ForbiddenError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error +from ...types.product import Product +from ...types.product_and_sk_us import ProductAndSkUs +from ...types.product_and_sk_us_list import ProductAndSkUsList +from ...types.publish_status import PublishStatus +from ...types.sku import Sku +from .types.product_sku_create_product import ProductSkuCreateProduct +from .types.product_sku_create_sku import ProductSkuCreateSku +from .types.products_create_sku_response import ProductsCreateSkuResponse +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawProductsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + site_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ProductAndSkUsList]: + """ + Retrieve all products for a site. + + Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product + will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. + + Required scope | `ecommerce:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ProductAndSkUsList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ProductAndSkUsList, + parse_obj_as( + type_=ProductAndSkUsList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create( + self, + site_id: str, + *, + product: ProductSkuCreateProduct, + sku: ProductSkuCreateSku, + publish_status: typing.Optional[PublishStatus] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ProductAndSkUs]: + """ + Create a new ecommerce product and defaultSKU. A product, at minimum, must have a single SKU. + + To create a product with multiple SKUs: + - First, create a list of `sku-properties`, also known as [product options](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). For example, a T-shirt product may have a "color" `sku-property`, with a list of enum values: red, yellow, and blue, another `sku-property` may be "size", with a list of enum values: small, medium, and large. + - Once, a product is created with a list of `sku-properties`, Webflow will create a **default SKU**, which is always a combination of the first `enum` values of each `sku-property`. (e.g. Small - Red - T-Shirt) + - After creation, you can create additional SKUs for the product, using the [Create SKUs endpoint.](/data/reference/ecommerce/products/create-sku) + + Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product : ProductSkuCreateProduct + + sku : ProductSkuCreateSku + + publish_status : typing.Optional[PublishStatus] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ProductAndSkUs] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "publishStatus": publish_status, + "product": convert_and_respect_annotation_metadata( + object_=product, annotation=ProductSkuCreateProduct, direction="write" + ), + "sku": convert_and_respect_annotation_metadata( + object_=sku, annotation=ProductSkuCreateSku, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ProductAndSkUs, + parse_obj_as( + type_=ProductAndSkUs, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get( + self, site_id: str, product_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[ProductAndSkUs]: + """ + Retrieve a single product by its ID. All of its SKUs will also be + retrieved. + + Required scope | `ecommerce:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ProductAndSkUs] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ProductAndSkUs, + parse_obj_as( + type_=ProductAndSkUs, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update( + self, + site_id: str, + product_id: str, + *, + publish_status: typing.Optional[PublishStatus] = OMIT, + product: typing.Optional[Product] = OMIT, + sku: typing.Optional[Sku] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Product]: + """ + Update an existing Product. + + Updating an existing Product will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product + + publish_status : typing.Optional[PublishStatus] + + product : typing.Optional[Product] + + sku : typing.Optional[Sku] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Product] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "publishStatus": publish_status, + "product": convert_and_respect_annotation_metadata( + object_=product, annotation=Product, direction="write" + ), + "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Product, + parse_obj_as( + type_=Product, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create_sku( + self, + site_id: str, + product_id: str, + *, + skus: typing.Sequence[Sku], + publish_status: typing.Optional[PublishStatus] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ProductsCreateSkuResponse]: + """ + Create additional SKUs to manage every [option and variant of your Product.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants) + + Creating SKUs through the API will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product + + skus : typing.Sequence[Sku] + An array of the SKU data your are adding + + publish_status : typing.Optional[PublishStatus] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ProductsCreateSkuResponse] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "publishStatus": publish_status, + "skus": convert_and_respect_annotation_metadata( + object_=skus, annotation=typing.Sequence[Sku], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ProductsCreateSkuResponse, + parse_obj_as( + type_=ProductsCreateSkuResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_sku( + self, + site_id: str, + product_id: str, + sku_id: str, + *, + sku: Sku, + publish_status: typing.Optional[PublishStatus] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Sku]: + """ + Update a specified SKU. + + Updating an existing SKU will set the Product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product + + sku_id : str + Unique identifier for a SKU + + sku : Sku + + publish_status : typing.Optional[PublishStatus] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Sku] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "publishStatus": publish_status, + "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Sku, + parse_obj_as( + type_=Sku, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawProductsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + site_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ProductAndSkUsList]: + """ + Retrieve all products for a site. + + Use `limit` and `offset` to page through all products with subsequent requests. All SKUs for each product + will also be fetched and returned. The `limit`, `offset` and `total` values represent Products only and do not include any SKUs. + + Required scope | `ecommerce:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ProductAndSkUsList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ProductAndSkUsList, + parse_obj_as( + type_=ProductAndSkUsList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create( + self, + site_id: str, + *, + product: ProductSkuCreateProduct, + sku: ProductSkuCreateSku, + publish_status: typing.Optional[PublishStatus] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ProductAndSkUs]: + """ + Create a new ecommerce product and defaultSKU. A product, at minimum, must have a single SKU. + + To create a product with multiple SKUs: + - First, create a list of `sku-properties`, also known as [product options](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants). For example, a T-shirt product may have a "color" `sku-property`, with a list of enum values: red, yellow, and blue, another `sku-property` may be "size", with a list of enum values: small, medium, and large. + - Once, a product is created with a list of `sku-properties`, Webflow will create a **default SKU**, which is always a combination of the first `enum` values of each `sku-property`. (e.g. Small - Red - T-Shirt) + - After creation, you can create additional SKUs for the product, using the [Create SKUs endpoint.](/data/reference/ecommerce/products/create-sku) + + Upon creation, the default product type will be `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product : ProductSkuCreateProduct + + sku : ProductSkuCreateSku + + publish_status : typing.Optional[PublishStatus] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ProductAndSkUs] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "publishStatus": publish_status, + "product": convert_and_respect_annotation_metadata( + object_=product, annotation=ProductSkuCreateProduct, direction="write" + ), + "sku": convert_and_respect_annotation_metadata( + object_=sku, annotation=ProductSkuCreateSku, direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ProductAndSkUs, + parse_obj_as( + type_=ProductAndSkUs, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get( + self, site_id: str, product_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[ProductAndSkUs]: + """ + Retrieve a single product by its ID. All of its SKUs will also be + retrieved. + + Required scope | `ecommerce:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ProductAndSkUs] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ProductAndSkUs, + parse_obj_as( + type_=ProductAndSkUs, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update( + self, + site_id: str, + product_id: str, + *, + publish_status: typing.Optional[PublishStatus] = OMIT, + product: typing.Optional[Product] = OMIT, + sku: typing.Optional[Sku] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Product]: + """ + Update an existing Product. + + Updating an existing Product will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product + + publish_status : typing.Optional[PublishStatus] + + product : typing.Optional[Product] + + sku : typing.Optional[Sku] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Product] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "publishStatus": publish_status, + "product": convert_and_respect_annotation_metadata( + object_=product, annotation=Product, direction="write" + ), + "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Product, + parse_obj_as( + type_=Product, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create_sku( + self, + site_id: str, + product_id: str, + *, + skus: typing.Sequence[Sku], + publish_status: typing.Optional[PublishStatus] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ProductsCreateSkuResponse]: + """ + Create additional SKUs to manage every [option and variant of your Product.](https://help.webflow.com/hc/en-us/articles/33961334531347-Create-product-options-and-variants) + + Creating SKUs through the API will set the product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product + + skus : typing.Sequence[Sku] + An array of the SKU data your are adding + + publish_status : typing.Optional[PublishStatus] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ProductsCreateSkuResponse] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "publishStatus": publish_status, + "skus": convert_and_respect_annotation_metadata( + object_=skus, annotation=typing.Sequence[Sku], direction="write" + ), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ProductsCreateSkuResponse, + parse_obj_as( + type_=ProductsCreateSkuResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_sku( + self, + site_id: str, + product_id: str, + sku_id: str, + *, + sku: Sku, + publish_status: typing.Optional[PublishStatus] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Sku]: + """ + Update a specified SKU. + + Updating an existing SKU will set the Product type to `Advanced`, which ensures all Product and SKU fields will be shown to users in the Designer. + + Required scope | `ecommerce:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + product_id : str + Unique identifier for a Product + + sku_id : str + Unique identifier for a SKU + + sku : Sku + + publish_status : typing.Optional[PublishStatus] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Sku] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/products/{jsonable_encoder(product_id)}/skus/{jsonable_encoder(sku_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "publishStatus": publish_status, + "sku": convert_and_respect_annotation_metadata(object_=sku, annotation=Sku, direction="write"), + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Sku, + parse_obj_as( + type_=Sku, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/products/types/__init__.py b/src/webflow/resources/products/types/__init__.py index 5b6d9b4..909ffe5 100644 --- a/src/webflow/resources/products/types/__init__.py +++ b/src/webflow/resources/products/types/__init__.py @@ -1,7 +1,40 @@ # This file was auto-generated by Fern from our API Definition. -from .product_sku_create_product import ProductSkuCreateProduct -from .product_sku_create_sku import ProductSkuCreateSku -from .products_create_sku_response import ProductsCreateSkuResponse +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .product_sku_create_product import ProductSkuCreateProduct + from .product_sku_create_sku import ProductSkuCreateSku + from .products_create_sku_response import ProductsCreateSkuResponse +_dynamic_imports: typing.Dict[str, str] = { + "ProductSkuCreateProduct": ".product_sku_create_product", + "ProductSkuCreateSku": ".product_sku_create_sku", + "ProductsCreateSkuResponse": ".products_create_sku_response", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["ProductSkuCreateProduct", "ProductSkuCreateSku", "ProductsCreateSkuResponse"] diff --git a/src/webflow/resources/products/types/product_sku_create_product.py b/src/webflow/resources/products/types/product_sku_create_product.py index 750e5f4..d35d712 100644 --- a/src/webflow/resources/products/types/product_sku_create_product.py +++ b/src/webflow/resources/products/types/product_sku_create_product.py @@ -1,16 +1,18 @@ # This file was auto-generated by Fern from our API Definition. -from ....core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ....types.product_field_data import ProductFieldData -from ....core.serialization import FieldMetadata -from ....core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +import typing_extensions +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.serialization import FieldMetadata +from ....types.product_field_data import ProductFieldData class ProductSkuCreateProduct(UniversalBaseModel): - field_data: typing_extensions.Annotated[typing.Optional[ProductFieldData], FieldMetadata(alias="fieldData")] = None + field_data: typing_extensions.Annotated[ + typing.Optional[ProductFieldData], FieldMetadata(alias="fieldData"), pydantic.Field(alias="fieldData") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/resources/products/types/product_sku_create_sku.py b/src/webflow/resources/products/types/product_sku_create_sku.py index 2762a9a..838e778 100644 --- a/src/webflow/resources/products/types/product_sku_create_sku.py +++ b/src/webflow/resources/products/types/product_sku_create_sku.py @@ -1,16 +1,18 @@ # This file was auto-generated by Fern from our API Definition. -from ....core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ....types.sku_field_data import SkuFieldData -from ....core.serialization import FieldMetadata -from ....core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +import typing_extensions +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.serialization import FieldMetadata +from ....types.sku_field_data import SkuFieldData class ProductSkuCreateSku(UniversalBaseModel): - field_data: typing_extensions.Annotated[typing.Optional[SkuFieldData], FieldMetadata(alias="fieldData")] = None + field_data: typing_extensions.Annotated[ + typing.Optional[SkuFieldData], FieldMetadata(alias="fieldData"), pydantic.Field(alias="fieldData") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/resources/products/types/products_create_sku_response.py b/src/webflow/resources/products/types/products_create_sku_response.py index cd68c3d..a498e9f 100644 --- a/src/webflow/resources/products/types/products_create_sku_response.py +++ b/src/webflow/resources/products/types/products_create_sku_response.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ....core.pydantic_utilities import UniversalBaseModel import typing -from ....types.sku import Sku -from ....core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....types.sku import Sku class ProductsCreateSkuResponse(UniversalBaseModel): diff --git a/src/webflow/resources/scripts/__init__.py b/src/webflow/resources/scripts/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/scripts/__init__.py +++ b/src/webflow/resources/scripts/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/scripts/client.py b/src/webflow/resources/scripts/client.py index 80026d9..f8a540e 100644 --- a/src/webflow/resources/scripts/client.py +++ b/src/webflow/resources/scripts/client.py @@ -1,22 +1,13 @@ # This file was auto-generated by Fern from our API Definition. import typing -from ...core.client_wrapper import SyncClientWrapper + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions -from ...types.registered_script_list import RegisteredScriptList -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.not_found_error import NotFoundError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError from ...types.custom_code_hosted_response import CustomCodeHostedResponse from ...types.custom_code_inline_response import CustomCodeInlineResponse -from ...core.client_wrapper import AsyncClientWrapper +from ...types.registered_script_list import RegisteredScriptList +from .raw_client import AsyncRawScriptsClient, RawScriptsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -24,7 +15,18 @@ class ScriptsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawScriptsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawScriptsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawScriptsClient + """ + return self._raw_client def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> RegisteredScriptList: """ @@ -60,75 +62,8 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/registered_scripts", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - RegisteredScriptList, - parse_obj_as( - type_=RegisteredScriptList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.list(site_id, request_options=request_options) + return _response.data def register_hosted( self, @@ -193,86 +128,16 @@ def register_hosted( display_name="displayName", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "hostedLocation": hosted_location, - "integrityHash": integrity_hash, - "canCopy": can_copy, - "version": version, - "displayName": display_name, - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.register_hosted( + site_id, + hosted_location=hosted_location, + integrity_hash=integrity_hash, + version=version, + display_name=display_name, + can_copy=can_copy, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CustomCodeHostedResponse, - parse_obj_as( - type_=CustomCodeHostedResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def register_inline( self, @@ -336,91 +201,32 @@ def register_inline( display_name="Alert", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "sourceCode": source_code, - "integrityHash": integrity_hash, - "canCopy": can_copy, - "version": version, - "displayName": display_name, - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.register_inline( + site_id, + source_code=source_code, + version=version, + display_name=display_name, + integrity_hash=integrity_hash, + can_copy=can_copy, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CustomCodeInlineResponse, - parse_obj_as( - type_=CustomCodeInlineResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data class AsyncScriptsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawScriptsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawScriptsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawScriptsClient + """ + return self._raw_client async def list( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -466,75 +272,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/registered_scripts", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - RegisteredScriptList, - parse_obj_as( - type_=RegisteredScriptList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.list(site_id, request_options=request_options) + return _response.data async def register_hosted( self, @@ -607,86 +346,16 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "hostedLocation": hosted_location, - "integrityHash": integrity_hash, - "canCopy": can_copy, - "version": version, - "displayName": display_name, - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.register_hosted( + site_id, + hosted_location=hosted_location, + integrity_hash=integrity_hash, + version=version, + display_name=display_name, + can_copy=can_copy, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CustomCodeHostedResponse, - parse_obj_as( - type_=CustomCodeHostedResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def register_inline( self, @@ -758,83 +427,13 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "sourceCode": source_code, - "integrityHash": integrity_hash, - "canCopy": can_copy, - "version": version, - "displayName": display_name, - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.register_inline( + site_id, + source_code=source_code, + version=version, + display_name=display_name, + integrity_hash=integrity_hash, + can_copy=can_copy, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CustomCodeInlineResponse, - parse_obj_as( - type_=CustomCodeInlineResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data diff --git a/src/webflow/resources/scripts/raw_client.py b/src/webflow/resources/scripts/raw_client.py new file mode 100644 index 0000000..0828f55 --- /dev/null +++ b/src/webflow/resources/scripts/raw_client.py @@ -0,0 +1,801 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...errors.bad_request_error import BadRequestError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.custom_code_hosted_response import CustomCodeHostedResponse +from ...types.custom_code_inline_response import CustomCodeInlineResponse +from ...types.error import Error +from ...types.registered_script_list import RegisteredScriptList +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawScriptsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[RegisteredScriptList]: + """ + Get a list of scripts that have been registered to a site. A site can have a maximum of 800 registered scripts. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[RegisteredScriptList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/registered_scripts", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + RegisteredScriptList, + parse_obj_as( + type_=RegisteredScriptList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def register_hosted( + self, + site_id: str, + *, + hosted_location: str, + integrity_hash: str, + version: str, + display_name: str, + can_copy: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CustomCodeHostedResponse]: + """ + Register a hosted script to a site. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + hosted_location : str + URI for an externally hosted script location + + integrity_hash : str + Sub-Resource Integrity Hash + + version : str + A Semantic Version (SemVer) string, denoting the version of the script + + display_name : str + User-facing name for the script. Must be between 1 and 50 alphanumeric characters + + can_copy : typing.Optional[bool] + Define whether the script can be copied on site duplication and transfer + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CustomCodeHostedResponse] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "hostedLocation": hosted_location, + "integrityHash": integrity_hash, + "canCopy": can_copy, + "version": version, + "displayName": display_name, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CustomCodeHostedResponse, + parse_obj_as( + type_=CustomCodeHostedResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def register_inline( + self, + site_id: str, + *, + source_code: str, + version: str, + display_name: str, + integrity_hash: typing.Optional[str] = OMIT, + can_copy: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CustomCodeInlineResponse]: + """ + Register an inline script to a site. Inline scripts are limited to 2000 characters. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + source_code : str + The code to be added to the site (to be hosted by Webflow). + + version : str + A Semantic Version (SemVer) string, denoting the version of the script + + display_name : str + User-facing name for the script. Must be between 1 and 50 alphanumeric characters + + integrity_hash : typing.Optional[str] + Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) + + can_copy : typing.Optional[bool] + Define whether the script can be copied on site duplication and transfer + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CustomCodeInlineResponse] + Created + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "sourceCode": source_code, + "integrityHash": integrity_hash, + "canCopy": can_copy, + "version": version, + "displayName": display_name, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CustomCodeInlineResponse, + parse_obj_as( + type_=CustomCodeInlineResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawScriptsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[RegisteredScriptList]: + """ + Get a list of scripts that have been registered to a site. A site can have a maximum of 800 registered scripts. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[RegisteredScriptList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/registered_scripts", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + RegisteredScriptList, + parse_obj_as( + type_=RegisteredScriptList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def register_hosted( + self, + site_id: str, + *, + hosted_location: str, + integrity_hash: str, + version: str, + display_name: str, + can_copy: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CustomCodeHostedResponse]: + """ + Register a hosted script to a site. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + hosted_location : str + URI for an externally hosted script location + + integrity_hash : str + Sub-Resource Integrity Hash + + version : str + A Semantic Version (SemVer) string, denoting the version of the script + + display_name : str + User-facing name for the script. Must be between 1 and 50 alphanumeric characters + + can_copy : typing.Optional[bool] + Define whether the script can be copied on site duplication and transfer + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CustomCodeHostedResponse] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/registered_scripts/hosted", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "hostedLocation": hosted_location, + "integrityHash": integrity_hash, + "canCopy": can_copy, + "version": version, + "displayName": display_name, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CustomCodeHostedResponse, + parse_obj_as( + type_=CustomCodeHostedResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def register_inline( + self, + site_id: str, + *, + source_code: str, + version: str, + display_name: str, + integrity_hash: typing.Optional[str] = OMIT, + can_copy: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CustomCodeInlineResponse]: + """ + Register an inline script to a site. Inline scripts are limited to 2000 characters. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + source_code : str + The code to be added to the site (to be hosted by Webflow). + + version : str + A Semantic Version (SemVer) string, denoting the version of the script + + display_name : str + User-facing name for the script. Must be between 1 and 50 alphanumeric characters + + integrity_hash : typing.Optional[str] + Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) + + can_copy : typing.Optional[bool] + Define whether the script can be copied on site duplication and transfer + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CustomCodeInlineResponse] + Created + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/registered_scripts/inline", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "sourceCode": source_code, + "integrityHash": integrity_hash, + "canCopy": can_copy, + "version": version, + "displayName": display_name, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CustomCodeInlineResponse, + parse_obj_as( + type_=CustomCodeInlineResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/sites/__init__.py b/src/webflow/resources/sites/__init__.py index c070ab2..fb81115 100644 --- a/src/webflow/resources/sites/__init__.py +++ b/src/webflow/resources/sites/__init__.py @@ -1,23 +1,69 @@ # This file was auto-generated by Fern from our API Definition. -from .types import SitesPublishResponse -from .resources import ( - CommentsGetCommentThreadRequestSortBy, - CommentsGetCommentThreadRequestSortOrder, - CommentsListCommentRepliesRequestSortBy, - CommentsListCommentRepliesRequestSortOrder, - CommentsListCommentThreadsRequestSortBy, - CommentsListCommentThreadsRequestSortOrder, - WellKnownFileContentType, - activity_logs, - comments, - forms, - plans, - redirects, - robots_txt, - scripts, - well_known, -) +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import SitesPublishResponse + from .resources import ( + CommentsGetCommentThreadRequestSortBy, + CommentsGetCommentThreadRequestSortOrder, + CommentsListCommentRepliesRequestSortBy, + CommentsListCommentRepliesRequestSortOrder, + CommentsListCommentThreadsRequestSortBy, + CommentsListCommentThreadsRequestSortOrder, + WellKnownFileContentType, + activity_logs, + comments, + forms, + plans, + redirects, + robots_txt, + scripts, + well_known, + ) +_dynamic_imports: typing.Dict[str, str] = { + "CommentsGetCommentThreadRequestSortBy": ".resources", + "CommentsGetCommentThreadRequestSortOrder": ".resources", + "CommentsListCommentRepliesRequestSortBy": ".resources", + "CommentsListCommentRepliesRequestSortOrder": ".resources", + "CommentsListCommentThreadsRequestSortBy": ".resources", + "CommentsListCommentThreadsRequestSortOrder": ".resources", + "SitesPublishResponse": ".types", + "WellKnownFileContentType": ".resources", + "activity_logs": ".resources", + "comments": ".resources", + "forms": ".resources", + "plans": ".resources", + "redirects": ".resources", + "robots_txt": ".resources", + "scripts": ".resources", + "well_known": ".resources", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "CommentsGetCommentThreadRequestSortBy", diff --git a/src/webflow/resources/sites/client.py b/src/webflow/resources/sites/client.py index 84b91bd..30b9ca2 100644 --- a/src/webflow/resources/sites/client.py +++ b/src/webflow/resources/sites/client.py @@ -1,56 +1,53 @@ # This file was auto-generated by Fern from our API Definition. +from __future__ import annotations + import typing -from ...core.client_wrapper import SyncClientWrapper -from .resources.redirects.client import RedirectsClient -from .resources.plans.client import PlansClient -from .resources.robots_txt.client import RobotsTxtClient -from .resources.well_known.client import WellKnownClient -from .resources.activity_logs.client import ActivityLogsClient -from .resources.comments.client import CommentsClient -from .resources.scripts.client import ScriptsClient -from .resources.forms.client import FormsClient + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions +from ...types.domains import Domains from ...types.site import Site -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.forbidden_error import ForbiddenError -from ...errors.not_found_error import NotFoundError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError from ...types.sites import Sites -from ...types.domains import Domains +from .raw_client import AsyncRawSitesClient, RawSitesClient from .types.sites_publish_response import SitesPublishResponse -from ...core.client_wrapper import AsyncClientWrapper -from .resources.redirects.client import AsyncRedirectsClient -from .resources.plans.client import AsyncPlansClient -from .resources.robots_txt.client import AsyncRobotsTxtClient -from .resources.well_known.client import AsyncWellKnownClient -from .resources.activity_logs.client import AsyncActivityLogsClient -from .resources.comments.client import AsyncCommentsClient -from .resources.scripts.client import AsyncScriptsClient -from .resources.forms.client import AsyncFormsClient +if typing.TYPE_CHECKING: + from .resources.activity_logs.client import ActivityLogsClient, AsyncActivityLogsClient + from .resources.comments.client import AsyncCommentsClient, CommentsClient + from .resources.forms.client import AsyncFormsClient, FormsClient + from .resources.plans.client import AsyncPlansClient, PlansClient + from .resources.redirects.client import AsyncRedirectsClient, RedirectsClient + from .resources.robots_txt.client import AsyncRobotsTxtClient, RobotsTxtClient + from .resources.scripts.client import AsyncScriptsClient, ScriptsClient + from .resources.well_known.client import AsyncWellKnownClient, WellKnownClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) class SitesClient: def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawSitesClient(client_wrapper=client_wrapper) self._client_wrapper = client_wrapper - self.redirects = RedirectsClient(client_wrapper=self._client_wrapper) - self.plans = PlansClient(client_wrapper=self._client_wrapper) - self.robots_txt = RobotsTxtClient(client_wrapper=self._client_wrapper) - self.well_known = WellKnownClient(client_wrapper=self._client_wrapper) - self.activity_logs = ActivityLogsClient(client_wrapper=self._client_wrapper) - self.comments = CommentsClient(client_wrapper=self._client_wrapper) - self.scripts = ScriptsClient(client_wrapper=self._client_wrapper) - self.forms = FormsClient(client_wrapper=self._client_wrapper) + self._redirects: typing.Optional[RedirectsClient] = None + self._plans: typing.Optional[PlansClient] = None + self._robots_txt: typing.Optional[RobotsTxtClient] = None + self._well_known: typing.Optional[WellKnownClient] = None + self._activity_logs: typing.Optional[ActivityLogsClient] = None + self._comments: typing.Optional[CommentsClient] = None + self._scripts: typing.Optional[ScriptsClient] = None + self._forms: typing.Optional[FormsClient] = None + + @property + def with_raw_response(self) -> RawSitesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawSitesClient + """ + return self._raw_client def create( self, @@ -102,94 +99,14 @@ def create( name="The Hitchhiker's Guide to the Galaxy", ) """ - _response = self._client_wrapper.httpx_client.request( - f"workspaces/{jsonable_encoder(workspace_id)}/sites", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "name": name, - "templateName": template_name, - "parentFolderId": parent_folder_id, - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.create( + workspace_id, + name=name, + template_name=template_name, + parent_folder_id=parent_folder_id, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Site, - parse_obj_as( - type_=Site, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Sites: """ @@ -216,55 +133,8 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Si ) client.sites.list() """ - _response = self._client_wrapper.httpx_client.request( - "sites", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Sites, - parse_obj_as( - type_=Sites, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.list(request_options=request_options) + return _response.data def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Site: """ @@ -296,75 +166,8 @@ def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Site, - parse_obj_as( - type_=Site, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get(site_id, request_options=request_options) + return _response.data def delete(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ @@ -397,79 +200,8 @@ def delete(self, site_id: str, *, request_options: typing.Optional[RequestOption site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete(site_id, request_options=request_options) + return _response.data def update( self, @@ -516,93 +248,10 @@ def update( site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "name": name, - "parentFolderId": parent_folder_id, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.update( + site_id, name=name, parent_folder_id=parent_folder_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Site, - parse_obj_as( - type_=Site, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get_custom_domain(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Domains: """ @@ -634,75 +283,8 @@ def get_custom_domain(self, site_id: str, *, request_options: typing.Optional[Re site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_domains", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Domains, - parse_obj_as( - type_=Domains, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get_custom_domain(site_id, request_options=request_options) + return _response.data def publish( self, @@ -753,96 +335,102 @@ def publish( publish_to_webflow_subdomain=False, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/publish", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "customDomains": custom_domains, - "publishToWebflowSubdomain": publish_to_webflow_subdomain, - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.publish( + site_id, + custom_domains=custom_domains, + publish_to_webflow_subdomain=publish_to_webflow_subdomain, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SitesPublishResponse, - parse_obj_as( - type_=SitesPublishResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data + + @property + def redirects(self): + if self._redirects is None: + from .resources.redirects.client import RedirectsClient # noqa: E402 + + self._redirects = RedirectsClient(client_wrapper=self._client_wrapper) + return self._redirects + + @property + def plans(self): + if self._plans is None: + from .resources.plans.client import PlansClient # noqa: E402 + + self._plans = PlansClient(client_wrapper=self._client_wrapper) + return self._plans + + @property + def robots_txt(self): + if self._robots_txt is None: + from .resources.robots_txt.client import RobotsTxtClient # noqa: E402 + + self._robots_txt = RobotsTxtClient(client_wrapper=self._client_wrapper) + return self._robots_txt + + @property + def well_known(self): + if self._well_known is None: + from .resources.well_known.client import WellKnownClient # noqa: E402 + + self._well_known = WellKnownClient(client_wrapper=self._client_wrapper) + return self._well_known + + @property + def activity_logs(self): + if self._activity_logs is None: + from .resources.activity_logs.client import ActivityLogsClient # noqa: E402 + + self._activity_logs = ActivityLogsClient(client_wrapper=self._client_wrapper) + return self._activity_logs + + @property + def comments(self): + if self._comments is None: + from .resources.comments.client import CommentsClient # noqa: E402 + + self._comments = CommentsClient(client_wrapper=self._client_wrapper) + return self._comments + + @property + def scripts(self): + if self._scripts is None: + from .resources.scripts.client import ScriptsClient # noqa: E402 + + self._scripts = ScriptsClient(client_wrapper=self._client_wrapper) + return self._scripts + + @property + def forms(self): + if self._forms is None: + from .resources.forms.client import FormsClient # noqa: E402 + + self._forms = FormsClient(client_wrapper=self._client_wrapper) + return self._forms class AsyncSitesClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawSitesClient(client_wrapper=client_wrapper) self._client_wrapper = client_wrapper - self.redirects = AsyncRedirectsClient(client_wrapper=self._client_wrapper) - self.plans = AsyncPlansClient(client_wrapper=self._client_wrapper) - self.robots_txt = AsyncRobotsTxtClient(client_wrapper=self._client_wrapper) - self.well_known = AsyncWellKnownClient(client_wrapper=self._client_wrapper) - self.activity_logs = AsyncActivityLogsClient(client_wrapper=self._client_wrapper) - self.comments = AsyncCommentsClient(client_wrapper=self._client_wrapper) - self.scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) - self.forms = AsyncFormsClient(client_wrapper=self._client_wrapper) + self._redirects: typing.Optional[AsyncRedirectsClient] = None + self._plans: typing.Optional[AsyncPlansClient] = None + self._robots_txt: typing.Optional[AsyncRobotsTxtClient] = None + self._well_known: typing.Optional[AsyncWellKnownClient] = None + self._activity_logs: typing.Optional[AsyncActivityLogsClient] = None + self._comments: typing.Optional[AsyncCommentsClient] = None + self._scripts: typing.Optional[AsyncScriptsClient] = None + self._forms: typing.Optional[AsyncFormsClient] = None + + @property + def with_raw_response(self) -> AsyncRawSitesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawSitesClient + """ + return self._raw_client async def create( self, @@ -902,94 +490,14 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"workspaces/{jsonable_encoder(workspace_id)}/sites", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "name": name, - "templateName": template_name, - "parentFolderId": parent_folder_id, - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.create( + workspace_id, + name=name, + template_name=template_name, + parent_folder_id=parent_folder_id, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Site, - parse_obj_as( - type_=Site, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> Sites: """ @@ -1024,55 +532,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "sites", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Sites, - parse_obj_as( - type_=Sites, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.list(request_options=request_options) + return _response.data async def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Site: """ @@ -1112,75 +573,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Site, - parse_obj_as( - type_=Site, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get(site_id, request_options=request_options) + return _response.data async def delete(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ @@ -1221,79 +615,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.delete(site_id, request_options=request_options) + return _response.data async def update( self, @@ -1348,93 +671,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "name": name, - "parentFolderId": parent_folder_id, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.update( + site_id, name=name, parent_folder_id=parent_folder_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Site, - parse_obj_as( - type_=Site, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get_custom_domain( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -1476,75 +716,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_domains", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Domains, - parse_obj_as( - type_=Domains, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get_custom_domain(site_id, request_options=request_options) + return _response.data async def publish( self, @@ -1603,80 +776,74 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/publish", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "customDomains": custom_domains, - "publishToWebflowSubdomain": publish_to_webflow_subdomain, - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.publish( + site_id, + custom_domains=custom_domains, + publish_to_webflow_subdomain=publish_to_webflow_subdomain, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SitesPublishResponse, - parse_obj_as( - type_=SitesPublishResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data + + @property + def redirects(self): + if self._redirects is None: + from .resources.redirects.client import AsyncRedirectsClient # noqa: E402 + + self._redirects = AsyncRedirectsClient(client_wrapper=self._client_wrapper) + return self._redirects + + @property + def plans(self): + if self._plans is None: + from .resources.plans.client import AsyncPlansClient # noqa: E402 + + self._plans = AsyncPlansClient(client_wrapper=self._client_wrapper) + return self._plans + + @property + def robots_txt(self): + if self._robots_txt is None: + from .resources.robots_txt.client import AsyncRobotsTxtClient # noqa: E402 + + self._robots_txt = AsyncRobotsTxtClient(client_wrapper=self._client_wrapper) + return self._robots_txt + + @property + def well_known(self): + if self._well_known is None: + from .resources.well_known.client import AsyncWellKnownClient # noqa: E402 + + self._well_known = AsyncWellKnownClient(client_wrapper=self._client_wrapper) + return self._well_known + + @property + def activity_logs(self): + if self._activity_logs is None: + from .resources.activity_logs.client import AsyncActivityLogsClient # noqa: E402 + + self._activity_logs = AsyncActivityLogsClient(client_wrapper=self._client_wrapper) + return self._activity_logs + + @property + def comments(self): + if self._comments is None: + from .resources.comments.client import AsyncCommentsClient # noqa: E402 + + self._comments = AsyncCommentsClient(client_wrapper=self._client_wrapper) + return self._comments + + @property + def scripts(self): + if self._scripts is None: + from .resources.scripts.client import AsyncScriptsClient # noqa: E402 + + self._scripts = AsyncScriptsClient(client_wrapper=self._client_wrapper) + return self._scripts + + @property + def forms(self): + if self._forms is None: + from .resources.forms.client import AsyncFormsClient # noqa: E402 + + self._forms = AsyncFormsClient(client_wrapper=self._client_wrapper) + return self._forms diff --git a/src/webflow/resources/sites/raw_client.py b/src/webflow/resources/sites/raw_client.py new file mode 100644 index 0000000..cc08250 --- /dev/null +++ b/src/webflow/resources/sites/raw_client.py @@ -0,0 +1,1587 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...errors.bad_request_error import BadRequestError +from ...errors.forbidden_error import ForbiddenError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.domains import Domains +from ...types.error import Error +from ...types.site import Site +from ...types.sites import Sites +from .types.sites_publish_response import SitesPublishResponse +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawSitesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def create( + self, + workspace_id: str, + *, + name: str, + template_name: typing.Optional[str] = OMIT, + parent_folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Site]: + """ + Create a site. + + This endpoint requires an Enterprise workspace. + + Required scope | `workspace:write` + + Parameters + ---------- + workspace_id : str + Unique identifier for a Workspace + + name : str + The name of the site + + template_name : typing.Optional[str] + The workspace or marketplace template to use + + parent_folder_id : typing.Optional[str] + MegaDodo Publications - Potential Book Ideas + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Site] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"workspaces/{jsonable_encoder(workspace_id)}/sites", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "name": name, + "templateName": template_name, + "parentFolderId": parent_folder_id, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Sites]: + """ + List of all sites the provided access token is able to access. + + Required scope | `sites:read` + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Sites] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + "sites", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Sites, + parse_obj_as( + type_=Sites, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Site]: + """ + Get details of a site. + + Required scope | `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Site] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[None]: + """ + Delete a site. + + This endpoint requires an Enterprise workspace. + + Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update( + self, + site_id: str, + *, + name: typing.Optional[str] = OMIT, + parent_folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Site]: + """ + Update a site. + + This endpoint requires an Enterprise workspace. + + Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + name : typing.Optional[str] + The name of the site + + parent_folder_id : typing.Optional[str] + The parent folder ID of the site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Site] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "name": name, + "parentFolderId": parent_folder_id, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_custom_domain( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[Domains]: + """ + Get a list of all custom domains related to site. + + Required scope | `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Domains] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/custom_domains", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Domains, + parse_obj_as( + type_=Domains, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def publish( + self, + site_id: str, + *, + custom_domains: typing.Optional[typing.Sequence[str]] = OMIT, + publish_to_webflow_subdomain: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[SitesPublishResponse]: + """ + Publishes a site to one or more more domains. + + To publish to a specific custom domain, use the domain IDs from the [Get Custom Domains](/data/reference/sites/get-custom-domain) endpoint. + + This endpoint has a specific rate limit of one successful publish queue per minute. + + Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + custom_domains : typing.Optional[typing.Sequence[str]] + Array of Custom Domain IDs to publish + + publish_to_webflow_subdomain : typing.Optional[bool] + Choice of whether to publish to the default Webflow Subdomain + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[SitesPublishResponse] + Request accepted + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/publish", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "customDomains": custom_domains, + "publishToWebflowSubdomain": publish_to_webflow_subdomain, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SitesPublishResponse, + parse_obj_as( + type_=SitesPublishResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawSitesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def create( + self, + workspace_id: str, + *, + name: str, + template_name: typing.Optional[str] = OMIT, + parent_folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Site]: + """ + Create a site. + + This endpoint requires an Enterprise workspace. + + Required scope | `workspace:write` + + Parameters + ---------- + workspace_id : str + Unique identifier for a Workspace + + name : str + The name of the site + + template_name : typing.Optional[str] + The workspace or marketplace template to use + + parent_folder_id : typing.Optional[str] + MegaDodo Publications - Potential Book Ideas + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Site] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"workspaces/{jsonable_encoder(workspace_id)}/sites", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "name": name, + "templateName": template_name, + "parentFolderId": parent_folder_id, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> AsyncHttpResponse[Sites]: + """ + List of all sites the provided access token is able to access. + + Required scope | `sites:read` + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Sites] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + "sites", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Sites, + parse_obj_as( + type_=Sites, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Site]: + """ + Get details of a site. + + Required scope | `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Site] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Delete a site. + + This endpoint requires an Enterprise workspace. + + Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update( + self, + site_id: str, + *, + name: typing.Optional[str] = OMIT, + parent_folder_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Site]: + """ + Update a site. + + This endpoint requires an Enterprise workspace. + + Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + name : typing.Optional[str] + The name of the site + + parent_folder_id : typing.Optional[str] + The parent folder ID of the site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Site] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "name": name, + "parentFolderId": parent_folder_id, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Site, + parse_obj_as( + type_=Site, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_custom_domain( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Domains]: + """ + Get a list of all custom domains related to site. + + Required scope | `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Domains] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/custom_domains", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Domains, + parse_obj_as( + type_=Domains, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def publish( + self, + site_id: str, + *, + custom_domains: typing.Optional[typing.Sequence[str]] = OMIT, + publish_to_webflow_subdomain: typing.Optional[bool] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[SitesPublishResponse]: + """ + Publishes a site to one or more more domains. + + To publish to a specific custom domain, use the domain IDs from the [Get Custom Domains](/data/reference/sites/get-custom-domain) endpoint. + + This endpoint has a specific rate limit of one successful publish queue per minute. + + Required scope | `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + custom_domains : typing.Optional[typing.Sequence[str]] + Array of Custom Domain IDs to publish + + publish_to_webflow_subdomain : typing.Optional[bool] + Choice of whether to publish to the default Webflow Subdomain + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[SitesPublishResponse] + Request accepted + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/publish", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "customDomains": custom_domains, + "publishToWebflowSubdomain": publish_to_webflow_subdomain, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SitesPublishResponse, + parse_obj_as( + type_=SitesPublishResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/sites/resources/__init__.py b/src/webflow/resources/sites/resources/__init__.py index 578d8dc..529b1de 100644 --- a/src/webflow/resources/sites/resources/__init__.py +++ b/src/webflow/resources/sites/resources/__init__.py @@ -1,15 +1,60 @@ # This file was auto-generated by Fern from our API Definition. -from . import activity_logs, comments, forms, plans, redirects, robots_txt, scripts, well_known -from .comments import ( - CommentsGetCommentThreadRequestSortBy, - CommentsGetCommentThreadRequestSortOrder, - CommentsListCommentRepliesRequestSortBy, - CommentsListCommentRepliesRequestSortOrder, - CommentsListCommentThreadsRequestSortBy, - CommentsListCommentThreadsRequestSortOrder, -) -from .well_known import WellKnownFileContentType +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from . import activity_logs, comments, forms, plans, redirects, robots_txt, scripts, well_known + from .comments import ( + CommentsGetCommentThreadRequestSortBy, + CommentsGetCommentThreadRequestSortOrder, + CommentsListCommentRepliesRequestSortBy, + CommentsListCommentRepliesRequestSortOrder, + CommentsListCommentThreadsRequestSortBy, + CommentsListCommentThreadsRequestSortOrder, + ) + from .well_known import WellKnownFileContentType +_dynamic_imports: typing.Dict[str, str] = { + "CommentsGetCommentThreadRequestSortBy": ".comments", + "CommentsGetCommentThreadRequestSortOrder": ".comments", + "CommentsListCommentRepliesRequestSortBy": ".comments", + "CommentsListCommentRepliesRequestSortOrder": ".comments", + "CommentsListCommentThreadsRequestSortBy": ".comments", + "CommentsListCommentThreadsRequestSortOrder": ".comments", + "WellKnownFileContentType": ".well_known", + "activity_logs": ".activity_logs", + "comments": ".comments", + "forms": ".forms", + "plans": ".plans", + "redirects": ".redirects", + "robots_txt": ".robots_txt", + "scripts": ".scripts", + "well_known": ".well_known", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "CommentsGetCommentThreadRequestSortBy", diff --git a/src/webflow/resources/sites/resources/activity_logs/__init__.py b/src/webflow/resources/sites/resources/activity_logs/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/sites/resources/activity_logs/__init__.py +++ b/src/webflow/resources/sites/resources/activity_logs/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/sites/resources/activity_logs/client.py b/src/webflow/resources/sites/resources/activity_logs/client.py index d36303b..1e999f7 100644 --- a/src/webflow/resources/sites/resources/activity_logs/client.py +++ b/src/webflow/resources/sites/resources/activity_logs/client.py @@ -1,24 +1,27 @@ # This file was auto-generated by Fern from our API Definition. -from .....core.client_wrapper import SyncClientWrapper import typing + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions from .....types.site_activity_log_response import SiteActivityLogResponse -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as -from .....errors.forbidden_error import ForbiddenError -from .....errors.not_found_error import NotFoundError -from .....types.error import Error -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError -from .....core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawActivityLogsClient, RawActivityLogsClient class ActivityLogsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawActivityLogsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawActivityLogsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawActivityLogsClient + """ + return self._raw_client def list( self, @@ -67,74 +70,24 @@ def list( offset=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/activity_logs", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "limit": limit, - "offset": offset, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SiteActivityLogResponse, - parse_obj_as( - type_=SiteActivityLogResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.list(site_id, limit=limit, offset=offset, request_options=request_options) + return _response.data class AsyncActivityLogsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawActivityLogsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawActivityLogsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawActivityLogsClient + """ + return self._raw_client async def list( self, @@ -191,66 +144,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/activity_logs", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "limit": limit, - "offset": offset, - }, - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SiteActivityLogResponse, - parse_obj_as( - type_=SiteActivityLogResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.list(site_id, limit=limit, offset=offset, request_options=request_options) + return _response.data diff --git a/src/webflow/resources/sites/resources/activity_logs/raw_client.py b/src/webflow/resources/sites/resources/activity_logs/raw_client.py new file mode 100644 index 0000000..4c6453a --- /dev/null +++ b/src/webflow/resources/sites/resources/activity_logs/raw_client.py @@ -0,0 +1,243 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....errors.forbidden_error import ForbiddenError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....types.error import Error +from .....types.site_activity_log_response import SiteActivityLogResponse +from pydantic import ValidationError + + +class RawActivityLogsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + site_id: str, + *, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[SiteActivityLogResponse]: + """ + Retrieve Activity Logs for a specific Site. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_activity:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[SiteActivityLogResponse] + A list of site activity logs + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/activity_logs", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SiteActivityLogResponse, + parse_obj_as( + type_=SiteActivityLogResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawActivityLogsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + site_id: str, + *, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[SiteActivityLogResponse]: + """ + Retrieve Activity Logs for a specific Site. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_activity:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[SiteActivityLogResponse] + A list of site activity logs + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/activity_logs", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "limit": limit, + "offset": offset, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SiteActivityLogResponse, + parse_obj_as( + type_=SiteActivityLogResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/sites/resources/comments/__init__.py b/src/webflow/resources/sites/resources/comments/__init__.py index 1bf96a0..91af2b0 100644 --- a/src/webflow/resources/sites/resources/comments/__init__.py +++ b/src/webflow/resources/sites/resources/comments/__init__.py @@ -1,13 +1,49 @@ # This file was auto-generated by Fern from our API Definition. -from .types import ( - CommentsGetCommentThreadRequestSortBy, - CommentsGetCommentThreadRequestSortOrder, - CommentsListCommentRepliesRequestSortBy, - CommentsListCommentRepliesRequestSortOrder, - CommentsListCommentThreadsRequestSortBy, - CommentsListCommentThreadsRequestSortOrder, -) +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import ( + CommentsGetCommentThreadRequestSortBy, + CommentsGetCommentThreadRequestSortOrder, + CommentsListCommentRepliesRequestSortBy, + CommentsListCommentRepliesRequestSortOrder, + CommentsListCommentThreadsRequestSortBy, + CommentsListCommentThreadsRequestSortOrder, + ) +_dynamic_imports: typing.Dict[str, str] = { + "CommentsGetCommentThreadRequestSortBy": ".types", + "CommentsGetCommentThreadRequestSortOrder": ".types", + "CommentsListCommentRepliesRequestSortBy": ".types", + "CommentsListCommentRepliesRequestSortOrder": ".types", + "CommentsListCommentThreadsRequestSortBy": ".types", + "CommentsListCommentThreadsRequestSortOrder": ".types", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "CommentsGetCommentThreadRequestSortBy", diff --git a/src/webflow/resources/sites/resources/comments/client.py b/src/webflow/resources/sites/resources/comments/client.py index 748e6e5..8fbae1e 100644 --- a/src/webflow/resources/sites/resources/comments/client.py +++ b/src/webflow/resources/sites/resources/comments/client.py @@ -1,33 +1,35 @@ # This file was auto-generated by Fern from our API Definition. -from .....core.client_wrapper import SyncClientWrapper import typing -from .types.comments_list_comment_threads_request_sort_by import CommentsListCommentThreadsRequestSortBy -from .types.comments_list_comment_threads_request_sort_order import CommentsListCommentThreadsRequestSortOrder + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions +from .....types.comment_reply_list import CommentReplyList +from .....types.comment_thread import CommentThread from .....types.comment_thread_list import CommentThreadList -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as -from .....errors.bad_request_error import BadRequestError -from .....errors.unauthorized_error import UnauthorizedError -from .....types.error import Error -from .....errors.not_found_error import NotFoundError -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError +from .raw_client import AsyncRawCommentsClient, RawCommentsClient from .types.comments_get_comment_thread_request_sort_by import CommentsGetCommentThreadRequestSortBy from .types.comments_get_comment_thread_request_sort_order import CommentsGetCommentThreadRequestSortOrder -from .....types.comment_thread import CommentThread from .types.comments_list_comment_replies_request_sort_by import CommentsListCommentRepliesRequestSortBy from .types.comments_list_comment_replies_request_sort_order import CommentsListCommentRepliesRequestSortOrder -from .....types.comment_reply_list import CommentReplyList -from .....core.client_wrapper import AsyncClientWrapper +from .types.comments_list_comment_threads_request_sort_by import CommentsListCommentThreadsRequestSortBy +from .types.comments_list_comment_threads_request_sort_order import CommentsListCommentThreadsRequestSortOrder class CommentsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawCommentsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawCommentsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawCommentsClient + """ + return self._raw_client def list_comment_threads( self, @@ -95,82 +97,16 @@ def list_comment_threads( sort_order="asc", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/comments", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "offset": offset, - "limit": limit, - "sortBy": sort_by, - "sortOrder": sort_order, - }, + _response = self._raw_client.list_comment_threads( + site_id, + locale_id=locale_id, + offset=offset, + limit=limit, + sort_by=sort_by, + sort_order=sort_order, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CommentThreadList, - parse_obj_as( - type_=CommentThreadList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get_comment_thread( self, @@ -243,82 +179,17 @@ def get_comment_thread( sort_order="asc", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "offset": offset, - "limit": limit, - "sortBy": sort_by, - "sortOrder": sort_order, - }, + _response = self._raw_client.get_comment_thread( + site_id, + comment_thread_id, + locale_id=locale_id, + offset=offset, + limit=limit, + sort_by=sort_by, + sort_order=sort_order, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CommentThread, - parse_obj_as( - type_=CommentThread, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def list_comment_replies( self, @@ -391,87 +262,33 @@ def list_comment_replies( sort_order="asc", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}/replies", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "offset": offset, - "limit": limit, - "sortBy": sort_by, - "sortOrder": sort_order, - }, + _response = self._raw_client.list_comment_replies( + site_id, + comment_thread_id, + locale_id=locale_id, + offset=offset, + limit=limit, + sort_by=sort_by, + sort_order=sort_order, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CommentReplyList, - parse_obj_as( - type_=CommentReplyList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data class AsyncCommentsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawCommentsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawCommentsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawCommentsClient + """ + return self._raw_client async def list_comment_threads( self, @@ -547,82 +364,16 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/comments", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "offset": offset, - "limit": limit, - "sortBy": sort_by, - "sortOrder": sort_order, - }, + _response = await self._raw_client.list_comment_threads( + site_id, + locale_id=locale_id, + offset=offset, + limit=limit, + sort_by=sort_by, + sort_order=sort_order, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CommentThreadList, - parse_obj_as( - type_=CommentThreadList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get_comment_thread( self, @@ -703,82 +454,17 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "offset": offset, - "limit": limit, - "sortBy": sort_by, - "sortOrder": sort_order, - }, + _response = await self._raw_client.get_comment_thread( + site_id, + comment_thread_id, + locale_id=locale_id, + offset=offset, + limit=limit, + sort_by=sort_by, + sort_order=sort_order, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CommentThread, - parse_obj_as( - type_=CommentThread, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def list_comment_replies( self, @@ -859,79 +545,14 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}/replies", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "localeId": locale_id, - "offset": offset, - "limit": limit, - "sortBy": sort_by, - "sortOrder": sort_order, - }, + _response = await self._raw_client.list_comment_replies( + site_id, + comment_thread_id, + locale_id=locale_id, + offset=offset, + limit=limit, + sort_by=sort_by, + sort_order=sort_order, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - CommentReplyList, - parse_obj_as( - type_=CommentReplyList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data diff --git a/src/webflow/resources/sites/resources/comments/raw_client.py b/src/webflow/resources/sites/resources/comments/raw_client.py new file mode 100644 index 0000000..9502f35 --- /dev/null +++ b/src/webflow/resources/sites/resources/comments/raw_client.py @@ -0,0 +1,876 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....errors.bad_request_error import BadRequestError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.comment_reply_list import CommentReplyList +from .....types.comment_thread import CommentThread +from .....types.comment_thread_list import CommentThreadList +from .....types.error import Error +from .types.comments_get_comment_thread_request_sort_by import CommentsGetCommentThreadRequestSortBy +from .types.comments_get_comment_thread_request_sort_order import CommentsGetCommentThreadRequestSortOrder +from .types.comments_list_comment_replies_request_sort_by import CommentsListCommentRepliesRequestSortBy +from .types.comments_list_comment_replies_request_sort_order import CommentsListCommentRepliesRequestSortOrder +from .types.comments_list_comment_threads_request_sort_by import CommentsListCommentThreadsRequestSortBy +from .types.comments_list_comment_threads_request_sort_order import CommentsListCommentThreadsRequestSortOrder +from pydantic import ValidationError + + +class RawCommentsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list_comment_threads( + self, + site_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsListCommentThreadsRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentThreadsRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CommentThreadList]: + """ + List all comment threads for a site. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentThreadsRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentThreadsRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CommentThreadList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CommentThreadList, + parse_obj_as( + type_=CommentThreadList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_comment_thread( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsGetCommentThreadRequestSortBy] = None, + sort_order: typing.Optional[CommentsGetCommentThreadRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CommentThread]: + """ + Get details of a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsGetCommentThreadRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsGetCommentThreadRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CommentThread] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CommentThread, + parse_obj_as( + type_=CommentThread, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def list_comment_replies( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsListCommentRepliesRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentRepliesRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CommentReplyList]: + """ + List all replies to a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentRepliesRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentRepliesRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CommentReplyList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}/replies", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CommentReplyList, + parse_obj_as( + type_=CommentReplyList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawCommentsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list_comment_threads( + self, + site_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsListCommentThreadsRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentThreadsRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CommentThreadList]: + """ + List all comment threads for a site. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentThreadsRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentThreadsRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CommentThreadList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CommentThreadList, + parse_obj_as( + type_=CommentThreadList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_comment_thread( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsGetCommentThreadRequestSortBy] = None, + sort_order: typing.Optional[CommentsGetCommentThreadRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CommentThread]: + """ + Get details of a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsGetCommentThreadRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsGetCommentThreadRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CommentThread] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CommentThread, + parse_obj_as( + type_=CommentThread, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def list_comment_replies( + self, + site_id: str, + comment_thread_id: str, + *, + locale_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + sort_by: typing.Optional[CommentsListCommentRepliesRequestSortBy] = None, + sort_order: typing.Optional[CommentsListCommentRepliesRequestSortOrder] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CommentReplyList]: + """ + List all replies to a specific comment thread. + + + There may be a delay of up to 5 minutes before new comments appear in the system. + + + Required scope | `comments:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + comment_thread_id : str + Unique identifier for a Comment Thread + + locale_id : typing.Optional[str] + Unique identifier for a specific Locale. + + [Lear more about localization.](/data/v2.0.0/docs/working-with-localization) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + sort_by : typing.Optional[CommentsListCommentRepliesRequestSortBy] + Sort results by the provided value. Only allowed when sortOrder is provided. + + sort_order : typing.Optional[CommentsListCommentRepliesRequestSortOrder] + Sorts the results by asc or desc + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CommentReplyList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/comments/{jsonable_encoder(comment_thread_id)}/replies", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "localeId": locale_id, + "offset": offset, + "limit": limit, + "sortBy": sort_by, + "sortOrder": sort_order, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CommentReplyList, + parse_obj_as( + type_=CommentReplyList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/sites/resources/comments/types/__init__.py b/src/webflow/resources/sites/resources/comments/types/__init__.py index 380d194..47e7b8b 100644 --- a/src/webflow/resources/sites/resources/comments/types/__init__.py +++ b/src/webflow/resources/sites/resources/comments/types/__init__.py @@ -1,11 +1,47 @@ # This file was auto-generated by Fern from our API Definition. -from .comments_get_comment_thread_request_sort_by import CommentsGetCommentThreadRequestSortBy -from .comments_get_comment_thread_request_sort_order import CommentsGetCommentThreadRequestSortOrder -from .comments_list_comment_replies_request_sort_by import CommentsListCommentRepliesRequestSortBy -from .comments_list_comment_replies_request_sort_order import CommentsListCommentRepliesRequestSortOrder -from .comments_list_comment_threads_request_sort_by import CommentsListCommentThreadsRequestSortBy -from .comments_list_comment_threads_request_sort_order import CommentsListCommentThreadsRequestSortOrder +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .comments_get_comment_thread_request_sort_by import CommentsGetCommentThreadRequestSortBy + from .comments_get_comment_thread_request_sort_order import CommentsGetCommentThreadRequestSortOrder + from .comments_list_comment_replies_request_sort_by import CommentsListCommentRepliesRequestSortBy + from .comments_list_comment_replies_request_sort_order import CommentsListCommentRepliesRequestSortOrder + from .comments_list_comment_threads_request_sort_by import CommentsListCommentThreadsRequestSortBy + from .comments_list_comment_threads_request_sort_order import CommentsListCommentThreadsRequestSortOrder +_dynamic_imports: typing.Dict[str, str] = { + "CommentsGetCommentThreadRequestSortBy": ".comments_get_comment_thread_request_sort_by", + "CommentsGetCommentThreadRequestSortOrder": ".comments_get_comment_thread_request_sort_order", + "CommentsListCommentRepliesRequestSortBy": ".comments_list_comment_replies_request_sort_by", + "CommentsListCommentRepliesRequestSortOrder": ".comments_list_comment_replies_request_sort_order", + "CommentsListCommentThreadsRequestSortBy": ".comments_list_comment_threads_request_sort_by", + "CommentsListCommentThreadsRequestSortOrder": ".comments_list_comment_threads_request_sort_order", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "CommentsGetCommentThreadRequestSortBy", diff --git a/src/webflow/resources/sites/resources/forms/__init__.py b/src/webflow/resources/sites/resources/forms/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/sites/resources/forms/__init__.py +++ b/src/webflow/resources/sites/resources/forms/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/sites/resources/forms/client.py b/src/webflow/resources/sites/resources/forms/client.py index 7b253a9..c165d82 100644 --- a/src/webflow/resources/sites/resources/forms/client.py +++ b/src/webflow/resources/sites/resources/forms/client.py @@ -1,23 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -from .....core.client_wrapper import SyncClientWrapper + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions -from .....types.form_submission_list import FormSubmissionList -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as -from .....errors.bad_request_error import BadRequestError -from .....errors.unauthorized_error import UnauthorizedError -from .....types.error import Error -from .....errors.forbidden_error import ForbiddenError -from .....errors.not_found_error import NotFoundError -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError from .....types.form_submission import FormSubmission -from .....errors.conflict_error import ConflictError -from .....core.client_wrapper import AsyncClientWrapper +from .....types.form_submission_list import FormSubmissionList +from .raw_client import AsyncRawFormsClient, RawFormsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -25,7 +14,18 @@ class FormsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawFormsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawFormsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawFormsClient + """ + return self._raw_client def list_submissions_by_site( self, @@ -85,90 +85,10 @@ def list_submissions_by_site( limit=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/form_submissions", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "elementId": element_id, - "offset": offset, - "limit": limit, - }, - request_options=request_options, + _response = self._raw_client.list_submissions_by_site( + site_id, element_id=element_id, offset=offset, limit=limit, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmissionList, - parse_obj_as( - type_=FormSubmissionList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def list_submissions( self, @@ -222,89 +142,10 @@ def list_submissions( limit=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/forms/{jsonable_encoder(form_id)}/submissions", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "offset": offset, - "limit": limit, - }, - request_options=request_options, + _response = self._raw_client.list_submissions( + site_id, form_id, offset=offset, limit=limit, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmissionList, - parse_obj_as( - type_=FormSubmissionList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get_submission( self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -342,85 +183,8 @@ def get_submission( form_submission_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmission, - parse_obj_as( - type_=FormSubmission, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get_submission(site_id, form_submission_id, request_options=request_options) + return _response.data def delete_submission( self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -457,96 +221,15 @@ def delete_submission( form_submission_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete_submission(site_id, form_submission_id, request_options=request_options) + return _response.data def update_submission( self, site_id: str, form_submission_id: str, *, - form_submission_data: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + form_submission_data: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> FormSubmission: """ @@ -562,7 +245,7 @@ def update_submission( form_submission_id : str Unique identifier for a Form Submission - form_submission_data : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] An existing **hidden field** defined on the form schema, and the corresponding value to set request_options : typing.Optional[RequestOptions] @@ -585,107 +268,26 @@ def update_submission( form_submission_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "formSubmissionData": form_submission_data, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.update_submission( + site_id, form_submission_id, form_submission_data=form_submission_data, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmission, - parse_obj_as( - type_=FormSubmission, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data class AsyncFormsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawFormsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawFormsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawFormsClient + """ + return self._raw_client async def list_submissions_by_site( self, @@ -753,90 +355,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/form_submissions", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "elementId": element_id, - "offset": offset, - "limit": limit, - }, - request_options=request_options, + _response = await self._raw_client.list_submissions_by_site( + site_id, element_id=element_id, offset=offset, limit=limit, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmissionList, - parse_obj_as( - type_=FormSubmissionList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def list_submissions( self, @@ -898,89 +420,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/forms/{jsonable_encoder(form_id)}/submissions", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "offset": offset, - "limit": limit, - }, - request_options=request_options, + _response = await self._raw_client.list_submissions( + site_id, form_id, offset=offset, limit=limit, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmissionList, - parse_obj_as( - type_=FormSubmissionList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get_submission( self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -1026,85 +469,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmission, - parse_obj_as( - type_=FormSubmission, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get_submission(site_id, form_submission_id, request_options=request_options) + return _response.data async def delete_submission( self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -1149,96 +515,17 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, + _response = await self._raw_client.delete_submission( + site_id, form_submission_id, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def update_submission( self, site_id: str, form_submission_id: str, *, - form_submission_data: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + form_submission_data: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> FormSubmission: """ @@ -1254,7 +541,7 @@ async def update_submission( form_submission_id : str Unique identifier for a Form Submission - form_submission_data : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] An existing **hidden field** defined on the form schema, and the corresponding value to set request_options : typing.Optional[RequestOptions] @@ -1285,99 +572,7 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "formSubmissionData": form_submission_data, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.update_submission( + site_id, form_submission_id, form_submission_data=form_submission_data, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - FormSubmission, - parse_obj_as( - type_=FormSubmission, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 409: - raise ConflictError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data diff --git a/src/webflow/resources/sites/resources/forms/raw_client.py b/src/webflow/resources/sites/resources/forms/raw_client.py new file mode 100644 index 0000000..c295236 --- /dev/null +++ b/src/webflow/resources/sites/resources/forms/raw_client.py @@ -0,0 +1,1330 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....errors.bad_request_error import BadRequestError +from .....errors.conflict_error import ConflictError +from .....errors.forbidden_error import ForbiddenError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....types.form_submission import FormSubmission +from .....types.form_submission_list import FormSubmissionList +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawFormsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list_submissions_by_site( + self, + site_id: str, + *, + element_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[FormSubmissionList]: + """ + List all form submissions for a given site with the ability to filter submissions by a centralized `elementId`. + + Add `elementId` when you want to filter form submissions to a specific form in a site. You can get the `elementId` from the [List forms endpoint](/data/reference/forms/forms/list) (displayed as `formElementId` in the response). + + + When a form is used in a Webflow component definition, each instance of the component will yield a unique form. Adding the `elementId` in this request ensures this API response includes all submissions from that core form, wherever that form is used in instantiated components. + + + Use the [List Form Submissions endpoint](/data/reference/forms/form-submissions/list-submissions) to list form submissions for a given form ID. + + Required scope | `forms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + element_id : typing.Optional[str] + Identifier for an element + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[FormSubmissionList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/form_submissions", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "elementId": element_id, + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmissionList, + parse_obj_as( + type_=FormSubmissionList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def list_submissions( + self, + site_id: str, + form_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[FormSubmissionList]: + """ + List form submissions for a given form ID within a specific site. + + Use the [List Form Submissions by Site endpoint](/data/reference/forms/form-submissions/list-submissions-by-site) to list form submissions for a given site with the ability to filter by a `formElementId`. + + Required scope | `forms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + form_id : str + Unique identifier for a Form + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[FormSubmissionList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/forms/{jsonable_encoder(form_id)}/submissions", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmissionList, + parse_obj_as( + type_=FormSubmissionList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get_submission( + self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[FormSubmission]: + """ + Get information about a form submission within a specific site. + + Required scope | `forms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[FormSubmission] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete_submission( + self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + Delete a form submission within a specific site. + + Required scope | `forms:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_submission( + self, + site_id: str, + form_submission_id: str, + *, + form_submission_data: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[FormSubmission]: + """ + Update hidden fields on a form submission within a specific site. + + Required scope | `forms:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + form_submission_id : str + Unique identifier for a Form Submission + + form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] + An existing **hidden field** defined on the form schema, and the corresponding value to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[FormSubmission] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "formSubmissionData": form_submission_data, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawFormsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list_submissions_by_site( + self, + site_id: str, + *, + element_id: typing.Optional[str] = None, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[FormSubmissionList]: + """ + List all form submissions for a given site with the ability to filter submissions by a centralized `elementId`. + + Add `elementId` when you want to filter form submissions to a specific form in a site. You can get the `elementId` from the [List forms endpoint](/data/reference/forms/forms/list) (displayed as `formElementId` in the response). + + + When a form is used in a Webflow component definition, each instance of the component will yield a unique form. Adding the `elementId` in this request ensures this API response includes all submissions from that core form, wherever that form is used in instantiated components. + + + Use the [List Form Submissions endpoint](/data/reference/forms/form-submissions/list-submissions) to list form submissions for a given form ID. + + Required scope | `forms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + element_id : typing.Optional[str] + Identifier for an element + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[FormSubmissionList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/form_submissions", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "elementId": element_id, + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmissionList, + parse_obj_as( + type_=FormSubmissionList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def list_submissions( + self, + site_id: str, + form_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[FormSubmissionList]: + """ + List form submissions for a given form ID within a specific site. + + Use the [List Form Submissions by Site endpoint](/data/reference/forms/form-submissions/list-submissions-by-site) to list form submissions for a given site with the ability to filter by a `formElementId`. + + Required scope | `forms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + form_id : str + Unique identifier for a Form + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[FormSubmissionList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/forms/{jsonable_encoder(form_id)}/submissions", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmissionList, + parse_obj_as( + type_=FormSubmissionList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get_submission( + self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[FormSubmission]: + """ + Get information about a form submission within a specific site. + + Required scope | `forms:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[FormSubmission] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete_submission( + self, site_id: str, form_submission_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Delete a form submission within a specific site. + + Required scope | `forms:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + form_submission_id : str + Unique identifier for a Form Submission + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_submission( + self, + site_id: str, + form_submission_id: str, + *, + form_submission_data: typing.Optional[typing.Dict[str, typing.Any]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[FormSubmission]: + """ + Update hidden fields on a form submission within a specific site. + + Required scope | `forms:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + form_submission_id : str + Unique identifier for a Form Submission + + form_submission_data : typing.Optional[typing.Dict[str, typing.Any]] + An existing **hidden field** defined on the form schema, and the corresponding value to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[FormSubmission] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/form_submissions/{jsonable_encoder(form_submission_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "formSubmissionData": form_submission_data, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + FormSubmission, + parse_obj_as( + type_=FormSubmission, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/sites/resources/plans/__init__.py b/src/webflow/resources/sites/resources/plans/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/sites/resources/plans/__init__.py +++ b/src/webflow/resources/sites/resources/plans/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/sites/resources/plans/client.py b/src/webflow/resources/sites/resources/plans/client.py index a3309bb..b9b9d0a 100644 --- a/src/webflow/resources/sites/resources/plans/client.py +++ b/src/webflow/resources/sites/resources/plans/client.py @@ -1,25 +1,27 @@ # This file was auto-generated by Fern from our API Definition. -from .....core.client_wrapper import SyncClientWrapper import typing + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions from .....types.site_plan import SitePlan -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as -from .....errors.bad_request_error import BadRequestError -from .....errors.unauthorized_error import UnauthorizedError -from .....types.error import Error -from .....errors.not_found_error import NotFoundError -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError -from .....core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawPlansClient, RawPlansClient class PlansClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawPlansClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawPlansClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawPlansClient + """ + return self._raw_client def get_site_plan(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> SitePlan: """ @@ -53,80 +55,24 @@ def get_site_plan(self, site_id: str, *, request_options: typing.Optional[Reques site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/plan", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SitePlan, - parse_obj_as( - type_=SitePlan, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get_site_plan(site_id, request_options=request_options) + return _response.data class AsyncPlansClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawPlansClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawPlansClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawPlansClient + """ + return self._raw_client async def get_site_plan(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> SitePlan: """ @@ -168,72 +114,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/plan", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - SitePlan, - parse_obj_as( - type_=SitePlan, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get_site_plan(site_id, request_options=request_options) + return _response.data diff --git a/src/webflow/resources/sites/resources/plans/raw_client.py b/src/webflow/resources/sites/resources/plans/raw_client.py new file mode 100644 index 0000000..c6f7bad --- /dev/null +++ b/src/webflow/resources/sites/resources/plans/raw_client.py @@ -0,0 +1,236 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....errors.bad_request_error import BadRequestError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....types.site_plan import SitePlan +from pydantic import ValidationError + + +class RawPlansClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_site_plan( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[SitePlan]: + """ + Get site plan details for the specified Site. + + This endpoint requires an Enterprise workspace. + + Required scope | `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[SitePlan] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/plan", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SitePlan, + parse_obj_as( + type_=SitePlan, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawPlansClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_site_plan( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[SitePlan]: + """ + Get site plan details for the specified Site. + + This endpoint requires an Enterprise workspace. + + Required scope | `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[SitePlan] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/plan", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + SitePlan, + parse_obj_as( + type_=SitePlan, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/sites/resources/redirects/__init__.py b/src/webflow/resources/sites/resources/redirects/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/sites/resources/redirects/__init__.py +++ b/src/webflow/resources/sites/resources/redirects/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/sites/resources/redirects/client.py b/src/webflow/resources/sites/resources/redirects/client.py index 1ac17b4..c2e1f7d 100644 --- a/src/webflow/resources/sites/resources/redirects/client.py +++ b/src/webflow/resources/sites/resources/redirects/client.py @@ -1,21 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -from .....core.client_wrapper import SyncClientWrapper + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions -from .....types.redirects import Redirects -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as -from .....errors.bad_request_error import BadRequestError -from .....errors.unauthorized_error import UnauthorizedError -from .....types.error import Error -from .....errors.not_found_error import NotFoundError -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError from .....types.redirect import Redirect -from .....core.client_wrapper import AsyncClientWrapper +from .....types.redirects import Redirects +from .raw_client import AsyncRawRedirectsClient, RawRedirectsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -23,7 +14,18 @@ class RedirectsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawRedirectsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawRedirectsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawRedirectsClient + """ + return self._raw_client def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Redirects: """ @@ -59,75 +61,8 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/redirects", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Redirects, - parse_obj_as( - type_=Redirects, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.list(site_id, request_options=request_options) + return _response.data def create( self, @@ -183,81 +118,10 @@ def create( to_url="/earth", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/redirects", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "id": id, - "fromUrl": from_url, - "toUrl": to_url, - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.create( + site_id, id=id, from_url=from_url, to_url=to_url, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Redirect, - parse_obj_as( - type_=Redirect, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def delete( self, site_id: str, redirect_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -277,7 +141,7 @@ def delete( Unique identifier for a Site redirect_id : str - Unique identifier site rediect + Unique identifier site redirect request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -299,75 +163,8 @@ def delete( redirect_id="66c4cb9a20cac35ed19500e6", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Redirects, - parse_obj_as( - type_=Redirects, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete(site_id, redirect_id, request_options=request_options) + return _response.data def update( self, @@ -392,7 +189,7 @@ def update( Unique identifier for a Site redirect_id : str - Unique identifier site rediect + Unique identifier site redirect id : typing.Optional[str] The ID of the specific redirect rule @@ -426,86 +223,26 @@ def update( to_url="/earth", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "id": id, - "fromUrl": from_url, - "toUrl": to_url, - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.update( + site_id, redirect_id, id=id, from_url=from_url, to_url=to_url, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Redirect, - parse_obj_as( - type_=Redirect, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data class AsyncRedirectsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawRedirectsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawRedirectsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawRedirectsClient + """ + return self._raw_client async def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Redirects: """ @@ -549,75 +286,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/redirects", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Redirects, - parse_obj_as( - type_=Redirects, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.list(site_id, request_options=request_options) + return _response.data async def create( self, @@ -681,81 +351,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/redirects", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "id": id, - "fromUrl": from_url, - "toUrl": to_url, - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.create( + site_id, id=id, from_url=from_url, to_url=to_url, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Redirect, - parse_obj_as( - type_=Redirect, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def delete( self, site_id: str, redirect_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -775,7 +374,7 @@ async def delete( Unique identifier for a Site redirect_id : str - Unique identifier site rediect + Unique identifier site redirect request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -805,75 +404,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Redirects, - parse_obj_as( - type_=Redirects, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.delete(site_id, redirect_id, request_options=request_options) + return _response.data async def update( self, @@ -898,7 +430,7 @@ async def update( Unique identifier for a Site redirect_id : str - Unique identifier site rediect + Unique identifier site redirect id : typing.Optional[str] The ID of the specific redirect rule @@ -940,78 +472,7 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "id": id, - "fromUrl": from_url, - "toUrl": to_url, - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.update( + site_id, redirect_id, id=id, from_url=from_url, to_url=to_url, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Redirect, - parse_obj_as( - type_=Redirect, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data diff --git a/src/webflow/resources/sites/resources/redirects/raw_client.py b/src/webflow/resources/sites/resources/redirects/raw_client.py new file mode 100644 index 0000000..d5abafe --- /dev/null +++ b/src/webflow/resources/sites/resources/redirects/raw_client.py @@ -0,0 +1,978 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....errors.bad_request_error import BadRequestError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....types.redirect import Redirect +from .....types.redirects import Redirects +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawRedirectsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Redirects]: + """ + Fetch a list of all 301 redirect rules configured for a specific site. + + Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + + This endpoint requires an Enterprise workspace. + + Required scope: `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Redirects] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Redirects, + parse_obj_as( + type_=Redirects, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create( + self, + site_id: str, + *, + id: typing.Optional[str] = OMIT, + from_url: typing.Optional[str] = OMIT, + to_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Redirect]: + """ + Add a new 301 redirection rule to a site. + + This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. + + This endpoint requires an Enterprise workspace. + + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + id : typing.Optional[str] + The ID of the specific redirect rule + + from_url : typing.Optional[str] + The source URL path that will be redirected. + + to_url : typing.Optional[str] + The target URL path where the user or client will be redirected. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Redirect] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "id": id, + "fromUrl": from_url, + "toUrl": to_url, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Redirect, + parse_obj_as( + type_=Redirect, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete( + self, site_id: str, redirect_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[Redirects]: + """ + Remove a 301 redirection rule from a site. + + This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + + This endpoint requires an Enterprise workspace. + + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + redirect_id : str + Unique identifier site redirect + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Redirects] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Redirects, + parse_obj_as( + type_=Redirects, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update( + self, + site_id: str, + redirect_id: str, + *, + id: typing.Optional[str] = OMIT, + from_url: typing.Optional[str] = OMIT, + to_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Redirect]: + """ + Update a 301 redirection rule from a site. + + This endpoint requires an Enterprise workspace. + + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + redirect_id : str + Unique identifier site redirect + + id : typing.Optional[str] + The ID of the specific redirect rule + + from_url : typing.Optional[str] + The source URL path that will be redirected. + + to_url : typing.Optional[str] + The target URL path where the user or client will be redirected. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Redirect] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "id": id, + "fromUrl": from_url, + "toUrl": to_url, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Redirect, + parse_obj_as( + type_=Redirect, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawRedirectsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Redirects]: + """ + Fetch a list of all 301 redirect rules configured for a specific site. + + Use this endpoint to review, audit, or manage the redirection rules that control how traffic is rerouted on your site. + + This endpoint requires an Enterprise workspace. + + Required scope: `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Redirects] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Redirects, + parse_obj_as( + type_=Redirects, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create( + self, + site_id: str, + *, + id: typing.Optional[str] = OMIT, + from_url: typing.Optional[str] = OMIT, + to_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Redirect]: + """ + Add a new 301 redirection rule to a site. + + This endpoint allows you to define a source path (`fromUrl`) and its corresponding destination path (`toUrl`), which will dictate how traffic is rerouted on your site. This is useful for managing site changes, restructuring URLs, or handling outdated links. + + This endpoint requires an Enterprise workspace. + + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + id : typing.Optional[str] + The ID of the specific redirect rule + + from_url : typing.Optional[str] + The source URL path that will be redirected. + + to_url : typing.Optional[str] + The target URL path where the user or client will be redirected. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Redirect] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "id": id, + "fromUrl": from_url, + "toUrl": to_url, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Redirect, + parse_obj_as( + type_=Redirect, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete( + self, site_id: str, redirect_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Redirects]: + """ + Remove a 301 redirection rule from a site. + + This is useful for cleaning up outdated or unnecessary redirects, ensuring that your site's routing behavior remains efficient and up-to-date. + + This endpoint requires an Enterprise workspace. + + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + redirect_id : str + Unique identifier site redirect + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Redirects] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Redirects, + parse_obj_as( + type_=Redirects, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update( + self, + site_id: str, + redirect_id: str, + *, + id: typing.Optional[str] = OMIT, + from_url: typing.Optional[str] = OMIT, + to_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Redirect]: + """ + Update a 301 redirection rule from a site. + + This endpoint requires an Enterprise workspace. + + Required scope: `sites:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + redirect_id : str + Unique identifier site redirect + + id : typing.Optional[str] + The ID of the specific redirect rule + + from_url : typing.Optional[str] + The source URL path that will be redirected. + + to_url : typing.Optional[str] + The target URL path where the user or client will be redirected. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Redirect] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/redirects/{jsonable_encoder(redirect_id)}", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "id": id, + "fromUrl": from_url, + "toUrl": to_url, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Redirect, + parse_obj_as( + type_=Redirect, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/sites/resources/robots_txt/__init__.py b/src/webflow/resources/sites/resources/robots_txt/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/sites/resources/robots_txt/__init__.py +++ b/src/webflow/resources/sites/resources/robots_txt/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/sites/resources/robots_txt/client.py b/src/webflow/resources/sites/resources/robots_txt/client.py index a0bc59b..af74b37 100644 --- a/src/webflow/resources/sites/resources/robots_txt/client.py +++ b/src/webflow/resources/sites/resources/robots_txt/client.py @@ -1,22 +1,12 @@ # This file was auto-generated by Fern from our API Definition. import typing -from .....core.client_wrapper import SyncClientWrapper + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions from .....types.robots import Robots -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as -from .....errors.bad_request_error import BadRequestError -from .....errors.unauthorized_error import UnauthorizedError -from .....types.error import Error -from .....errors.not_found_error import NotFoundError -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError from .....types.robots_rules_item import RobotsRulesItem -from .....core.serialization import convert_and_respect_annotation_metadata -from .....core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawRobotsTxtClient, RawRobotsTxtClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -24,7 +14,18 @@ class RobotsTxtClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawRobotsTxtClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawRobotsTxtClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawRobotsTxtClient + """ + return self._raw_client def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Robots: """ @@ -58,75 +59,8 @@ def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/robots_txt", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Robots, - parse_obj_as( - type_=Robots, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get(site_id, request_options=request_options) + return _response.data def put( self, @@ -181,82 +115,8 @@ def put( sitemap="https://heartofgold.ship/sitemap.xml", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/robots_txt", - base_url=self._client_wrapper.get_environment().base, - method="PUT", - json={ - "rules": convert_and_respect_annotation_metadata( - object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" - ), - "sitemap": sitemap, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Robots, - parse_obj_as( - type_=Robots, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.put(site_id, rules=rules, sitemap=sitemap, request_options=request_options) + return _response.data def delete( self, @@ -312,82 +172,8 @@ def delete( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/robots_txt", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - json={ - "rules": convert_and_respect_annotation_metadata( - object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" - ), - "sitemap": sitemap, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Robots, - parse_obj_as( - type_=Robots, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete(site_id, rules=rules, sitemap=sitemap, request_options=request_options) + return _response.data def patch( self, @@ -442,87 +228,24 @@ def patch( sitemap="https://heartofgold.ship/sitemap.xml", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/robots_txt", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "rules": convert_and_respect_annotation_metadata( - object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" - ), - "sitemap": sitemap, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Robots, - parse_obj_as( - type_=Robots, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.patch(site_id, rules=rules, sitemap=sitemap, request_options=request_options) + return _response.data class AsyncRobotsTxtClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawRobotsTxtClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawRobotsTxtClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawRobotsTxtClient + """ + return self._raw_client async def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Robots: """ @@ -564,75 +287,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/robots_txt", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Robots, - parse_obj_as( - type_=Robots, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get(site_id, request_options=request_options) + return _response.data async def put( self, @@ -695,82 +351,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/robots_txt", - base_url=self._client_wrapper.get_environment().base, - method="PUT", - json={ - "rules": convert_and_respect_annotation_metadata( - object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" - ), - "sitemap": sitemap, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Robots, - parse_obj_as( - type_=Robots, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.put(site_id, rules=rules, sitemap=sitemap, request_options=request_options) + return _response.data async def delete( self, @@ -834,82 +416,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/robots_txt", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - json={ - "rules": convert_and_respect_annotation_metadata( - object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" - ), - "sitemap": sitemap, - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.delete( + site_id, rules=rules, sitemap=sitemap, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Robots, - parse_obj_as( - type_=Robots, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def patch( self, @@ -972,79 +482,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/robots_txt", - base_url=self._client_wrapper.get_environment().base, - method="PATCH", - json={ - "rules": convert_and_respect_annotation_metadata( - object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" - ), - "sitemap": sitemap, - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Robots, - parse_obj_as( - type_=Robots, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.patch(site_id, rules=rules, sitemap=sitemap, request_options=request_options) + return _response.data diff --git a/src/webflow/resources/sites/resources/robots_txt/raw_client.py b/src/webflow/resources/sites/resources/robots_txt/raw_client.py new file mode 100644 index 0000000..ac8d1fe --- /dev/null +++ b/src/webflow/resources/sites/resources/robots_txt/raw_client.py @@ -0,0 +1,987 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....core.serialization import convert_and_respect_annotation_metadata +from .....errors.bad_request_error import BadRequestError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....types.robots import Robots +from .....types.robots_rules_item import RobotsRulesItem +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawRobotsTxtClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Robots]: + """ + Retrieve the robots.txt configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Robots] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def put( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Robots]: + """ + Replace the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Robots] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Robots]: + """ + Remove specific rules for a user-agent in your `robots.txt` file. To delete all rules for a user-agent, provide an empty rule set. This will remove the user-agent's entry entirely, leaving it subject to your site's default crawling behavior. + + **Note:** Deleting a user-agent with no rules will make the user-agent's access unrestricted unless other directives apply. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Robots] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def patch( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Robots]: + """ + Update the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Robots] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawRobotsTxtClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Robots]: + """ + Retrieve the robots.txt configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Robots] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def put( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Robots]: + """ + Replace the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Robots] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Robots]: + """ + Remove specific rules for a user-agent in your `robots.txt` file. To delete all rules for a user-agent, provide an empty rule set. This will remove the user-agent's entry entirely, leaving it subject to your site's default crawling behavior. + + **Note:** Deleting a user-agent with no rules will make the user-agent's access unrestricted unless other directives apply. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Robots] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def patch( + self, + site_id: str, + *, + rules: typing.Optional[typing.Sequence[RobotsRulesItem]] = OMIT, + sitemap: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Robots]: + """ + Update the `robots.txt` configuration for various user agents. + + This endpoint requires an Enterprise workspace. + + Required scope | `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + rules : typing.Optional[typing.Sequence[RobotsRulesItem]] + List of rules for user agents. + + sitemap : typing.Optional[str] + URL to the sitemap. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Robots] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/robots_txt", + base_url=self._client_wrapper.get_environment().base, + method="PATCH", + json={ + "rules": convert_and_respect_annotation_metadata( + object_=rules, annotation=typing.Sequence[RobotsRulesItem], direction="write" + ), + "sitemap": sitemap, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Robots, + parse_obj_as( + type_=Robots, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/sites/resources/scripts/__init__.py b/src/webflow/resources/sites/resources/scripts/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/sites/resources/scripts/__init__.py +++ b/src/webflow/resources/sites/resources/scripts/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/sites/resources/scripts/client.py b/src/webflow/resources/sites/resources/scripts/client.py index 7966e56..f7cddec 100644 --- a/src/webflow/resources/sites/resources/scripts/client.py +++ b/src/webflow/resources/sites/resources/scripts/client.py @@ -1,23 +1,13 @@ # This file was auto-generated by Fern from our API Definition. import typing -from .....core.client_wrapper import SyncClientWrapper + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions -from .....types.script_apply_list import ScriptApplyList -from .....core.jsonable_encoder import jsonable_encoder -from .....core.pydantic_utilities import parse_obj_as -from .....errors.bad_request_error import BadRequestError -from .....errors.unauthorized_error import UnauthorizedError -from .....types.error import Error -from .....errors.not_found_error import NotFoundError -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError -from .....types.script_apply import ScriptApply -from .....core.serialization import convert_and_respect_annotation_metadata from .....types.list_custom_code_blocks import ListCustomCodeBlocks -from .....core.client_wrapper import AsyncClientWrapper +from .....types.script_apply import ScriptApply +from .....types.script_apply_list import ScriptApplyList +from .raw_client import AsyncRawScriptsClient, RawScriptsClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -25,7 +15,18 @@ class ScriptsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawScriptsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawScriptsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawScriptsClient + """ + return self._raw_client def get_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -63,75 +64,8 @@ def get_custom_code( site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ScriptApplyList, - parse_obj_as( - type_=ScriptApplyList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get_custom_code(site_id, request_options=request_options) + return _response.data def upsert_custom_code( self, @@ -197,83 +131,10 @@ def upsert_custom_code( ], ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="PUT", - json={ - "scripts": convert_and_respect_annotation_metadata( - object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" - ), - "lastUpdated": last_updated, - "createdOn": created_on, - }, - request_options=request_options, - omit=OMIT, + _response = self._raw_client.upsert_custom_code( + site_id, scripts=scripts, last_updated=last_updated, created_on=created_on, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ScriptApplyList, - parse_obj_as( - type_=ScriptApplyList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def delete_custom_code(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ @@ -308,69 +169,8 @@ def delete_custom_code(self, site_id: str, *, request_options: typing.Optional[R site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete_custom_code(site_id, request_options=request_options) + return _response.data def list_custom_code_blocks( self, @@ -423,84 +223,26 @@ def list_custom_code_blocks( limit=1, ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "offset": offset, - "limit": limit, - }, - request_options=request_options, + _response = self._raw_client.list_custom_code_blocks( + site_id, offset=offset, limit=limit, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListCustomCodeBlocks, - parse_obj_as( - type_=ListCustomCodeBlocks, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data class AsyncScriptsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawScriptsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawScriptsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawScriptsClient + """ + return self._raw_client async def get_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -546,75 +288,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ScriptApplyList, - parse_obj_as( - type_=ScriptApplyList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get_custom_code(site_id, request_options=request_options) + return _response.data async def upsert_custom_code( self, @@ -688,83 +363,10 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="PUT", - json={ - "scripts": convert_and_respect_annotation_metadata( - object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" - ), - "lastUpdated": last_updated, - "createdOn": created_on, - }, - request_options=request_options, - omit=OMIT, + _response = await self._raw_client.upsert_custom_code( + site_id, scripts=scripts, last_updated=last_updated, created_on=created_on, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ScriptApplyList, - parse_obj_as( - type_=ScriptApplyList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def delete_custom_code( self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None @@ -809,69 +411,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.delete_custom_code(site_id, request_options=request_options) + return _response.data async def list_custom_code_blocks( self, @@ -932,76 +473,7 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "offset": offset, - "limit": limit, - }, - request_options=request_options, + _response = await self._raw_client.list_custom_code_blocks( + site_id, offset=offset, limit=limit, request_options=request_options ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - ListCustomCodeBlocks, - parse_obj_as( - type_=ListCustomCodeBlocks, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data diff --git a/src/webflow/resources/sites/resources/scripts/raw_client.py b/src/webflow/resources/sites/resources/scripts/raw_client.py new file mode 100644 index 0000000..a5e6bb6 --- /dev/null +++ b/src/webflow/resources/sites/resources/scripts/raw_client.py @@ -0,0 +1,946 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....core.serialization import convert_and_respect_annotation_metadata +from .....errors.bad_request_error import BadRequestError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....types.list_custom_code_blocks import ListCustomCodeBlocks +from .....types.script_apply import ScriptApply +from .....types.script_apply_list import ScriptApplyList +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawScriptsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_custom_code( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[ScriptApplyList]: + """ + Get all scripts applied to a site by the App. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ScriptApplyList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def upsert_custom_code( + self, + site_id: str, + *, + scripts: typing.Optional[typing.Sequence[ScriptApply]] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ScriptApplyList]: + """ + Apply registered scripts to a site. If you have multiple scripts your App needs to apply or maintain on a site, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + scripts : typing.Optional[typing.Sequence[ScriptApply]] + A list of scripts applied to a Site or a Page + + last_updated : typing.Optional[str] + Date when the Site's scripts were last updated + + created_on : typing.Optional[str] + Date when the Site's scripts were created + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ScriptApplyList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "scripts": convert_and_respect_annotation_metadata( + object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" + ), + "lastUpdated": last_updated, + "createdOn": created_on, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete_custom_code( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + Remove all scripts from a site applied by the App. This endpoint will not remove scripts from the site's registered scripts. + + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-sites/upsert-custom-code) endpoint. + + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). + + Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def list_custom_code_blocks( + self, + site_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ListCustomCodeBlocks]: + """ + Get a list of scripts that have been applied to a site and/or individual pages. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. + + See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ListCustomCodeBlocks] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ListCustomCodeBlocks, + parse_obj_as( + type_=ListCustomCodeBlocks, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawScriptsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_custom_code( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[ScriptApplyList]: + """ + Get all scripts applied to a site by the App. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ScriptApplyList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def upsert_custom_code( + self, + site_id: str, + *, + scripts: typing.Optional[typing.Sequence[ScriptApply]] = OMIT, + last_updated: typing.Optional[str] = OMIT, + created_on: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ScriptApplyList]: + """ + Apply registered scripts to a site. If you have multiple scripts your App needs to apply or maintain on a site, ensure they are always included in the request body for this endpoint. To remove individual scripts, simply call this endpoint without the script in the request body. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + scripts : typing.Optional[typing.Sequence[ScriptApply]] + A list of scripts applied to a Site or a Page + + last_updated : typing.Optional[str] + Date when the Site's scripts were last updated + + created_on : typing.Optional[str] + Date when the Site's scripts were created + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ScriptApplyList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "scripts": convert_and_respect_annotation_metadata( + object_=scripts, annotation=typing.Sequence[ScriptApply], direction="write" + ), + "lastUpdated": last_updated, + "createdOn": created_on, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ScriptApplyList, + parse_obj_as( + type_=ScriptApplyList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete_custom_code( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Remove all scripts from a site applied by the App. This endpoint will not remove scripts from the site's registered scripts. + + To remove individual scripts applied by the App, use the [Add/Update Custom Code](/data/reference/custom-code/custom-code-sites/upsert-custom-code) endpoint. + + Access to this endpoint requires a bearer token obtained from an [OAuth Code Grant Flow](/data/reference/oauth-app). + + Required scope | `custom_code:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/custom_code", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def list_custom_code_blocks( + self, + site_id: str, + *, + offset: typing.Optional[int] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ListCustomCodeBlocks]: + """ + Get a list of scripts that have been applied to a site and/or individual pages. + + + To apply a script to a site or page, the script must first be registered to a site via the [Register Script](/data/reference/custom-code/custom-code/register-hosted) endpoints. Once registered, the script can be applied to a Site or Page using the appropriate endpoints. + + See the documentation on [working with Custom Code](/data/docs/custom-code) for more information. + + + Required scope | `custom_code:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ListCustomCodeBlocks] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/custom_code/blocks", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "offset": offset, + "limit": limit, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ListCustomCodeBlocks, + parse_obj_as( + type_=ListCustomCodeBlocks, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/sites/resources/well_known/__init__.py b/src/webflow/resources/sites/resources/well_known/__init__.py index 323b6bd..34fc810 100644 --- a/src/webflow/resources/sites/resources/well_known/__init__.py +++ b/src/webflow/resources/sites/resources/well_known/__init__.py @@ -1,5 +1,34 @@ # This file was auto-generated by Fern from our API Definition. -from .types import WellKnownFileContentType +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import WellKnownFileContentType +_dynamic_imports: typing.Dict[str, str] = {"WellKnownFileContentType": ".types"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["WellKnownFileContentType"] diff --git a/src/webflow/resources/sites/resources/well_known/client.py b/src/webflow/resources/sites/resources/well_known/client.py index 3bba9ab..14c76ae 100644 --- a/src/webflow/resources/sites/resources/well_known/client.py +++ b/src/webflow/resources/sites/resources/well_known/client.py @@ -1,20 +1,11 @@ # This file was auto-generated by Fern from our API Definition. import typing -from .....core.client_wrapper import SyncClientWrapper -from .types.well_known_file_content_type import WellKnownFileContentType + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions -from .....core.jsonable_encoder import jsonable_encoder -from .....errors.bad_request_error import BadRequestError -from .....core.pydantic_utilities import parse_obj_as -from .....errors.unauthorized_error import UnauthorizedError -from .....types.error import Error -from .....errors.not_found_error import NotFoundError -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError -from .....core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawWellKnownClient, RawWellKnownClient +from .types.well_known_file_content_type import WellKnownFileContentType # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -22,7 +13,18 @@ class WellKnownClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawWellKnownClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawWellKnownClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawWellKnownClient + """ + return self._raw_client def put( self, @@ -84,78 +86,14 @@ def put( content_type="application/json", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/well_known", - base_url=self._client_wrapper.get_environment().base, - method="PUT", - json={ - "fileName": file_name, - "fileData": file_data, - "contentType": content_type, - }, - headers={ - "content-type": "application/json", - }, + _response = self._raw_client.put( + site_id, + file_name=file_name, + file_data=file_data, + content_type=content_type, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def delete( self, @@ -197,81 +135,24 @@ def delete( site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/well_known", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - json={ - "fileNames": file_names, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete(site_id, file_names=file_names, request_options=request_options) + return _response.data class AsyncWellKnownClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawWellKnownClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawWellKnownClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawWellKnownClient + """ + return self._raw_client async def put( self, @@ -341,78 +222,14 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/well_known", - base_url=self._client_wrapper.get_environment().base, - method="PUT", - json={ - "fileName": file_name, - "fileData": file_data, - "contentType": content_type, - }, - headers={ - "content-type": "application/json", - }, + _response = await self._raw_client.put( + site_id, + file_name=file_name, + file_data=file_data, + content_type=content_type, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def delete( self, @@ -462,73 +279,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/well_known", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - json={ - "fileNames": file_names, - }, - headers={ - "content-type": "application/json", - }, - request_options=request_options, - omit=OMIT, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.delete(site_id, file_names=file_names, request_options=request_options) + return _response.data diff --git a/src/webflow/resources/sites/resources/well_known/raw_client.py b/src/webflow/resources/sites/resources/well_known/raw_client.py new file mode 100644 index 0000000..7125705 --- /dev/null +++ b/src/webflow/resources/sites/resources/well_known/raw_client.py @@ -0,0 +1,507 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....errors.bad_request_error import BadRequestError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .types.well_known_file_content_type import WellKnownFileContentType +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawWellKnownClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def put( + self, + site_id: str, + *, + file_name: str, + file_data: str, + content_type: typing.Optional[WellKnownFileContentType] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Upload a supported well-known file to a site. + + The current restrictions on well-known files are as follows: + - Each file must be smaller than 100kb + - Less than 30 total files + - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` + + + `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. + + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_name : str + The name of the file + + file_data : str + The contents of the file + + content_type : typing.Optional[WellKnownFileContentType] + The content type of the file. Defaults to application/json + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "fileName": file_name, + "fileData": file_data, + "contentType": content_type, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete( + self, + site_id: str, + *, + file_names: typing.Optional[typing.Sequence[str]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Delete existing well-known files from a site. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_names : typing.Optional[typing.Sequence[str]] + A list of file names to delete + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "fileNames": file_names, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawWellKnownClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def put( + self, + site_id: str, + *, + file_name: str, + file_data: str, + content_type: typing.Optional[WellKnownFileContentType] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Upload a supported well-known file to a site. + + The current restrictions on well-known files are as follows: + - Each file must be smaller than 100kb + - Less than 30 total files + - Have one of the following file extensions (or no extension): `.txt`, `.json`, `.noext` + + + `.noext` is a special file extension that removes other extensions. For example, `apple-app-site-association.noext.txt` will be uploaded as `apple-app-site-association`. Use this extension for tools that have trouble uploading extensionless files. + + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_name : str + The name of the file + + file_data : str + The contents of the file + + content_type : typing.Optional[WellKnownFileContentType] + The content type of the file. Defaults to application/json + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="PUT", + json={ + "fileName": file_name, + "fileData": file_data, + "contentType": content_type, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete( + self, + site_id: str, + *, + file_names: typing.Optional[typing.Sequence[str]] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Delete existing well-known files from a site. + + This endpoint requires an Enterprise workspace. + + Required scope: `site_config:write` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + file_names : typing.Optional[typing.Sequence[str]] + A list of file names to delete + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/well_known", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + json={ + "fileNames": file_names, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/sites/resources/well_known/types/__init__.py b/src/webflow/resources/sites/resources/well_known/types/__init__.py index 4fc9c09..a5ec3aa 100644 --- a/src/webflow/resources/sites/resources/well_known/types/__init__.py +++ b/src/webflow/resources/sites/resources/well_known/types/__init__.py @@ -1,5 +1,34 @@ # This file was auto-generated by Fern from our API Definition. -from .well_known_file_content_type import WellKnownFileContentType +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .well_known_file_content_type import WellKnownFileContentType +_dynamic_imports: typing.Dict[str, str] = {"WellKnownFileContentType": ".well_known_file_content_type"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["WellKnownFileContentType"] diff --git a/src/webflow/resources/sites/types/__init__.py b/src/webflow/resources/sites/types/__init__.py index c85fd30..960aec6 100644 --- a/src/webflow/resources/sites/types/__init__.py +++ b/src/webflow/resources/sites/types/__init__.py @@ -1,5 +1,34 @@ # This file was auto-generated by Fern from our API Definition. -from .sites_publish_response import SitesPublishResponse +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .sites_publish_response import SitesPublishResponse +_dynamic_imports: typing.Dict[str, str] = {"SitesPublishResponse": ".sites_publish_response"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["SitesPublishResponse"] diff --git a/src/webflow/resources/sites/types/sites_publish_response.py b/src/webflow/resources/sites/types/sites_publish_response.py index bf7a95b..d32e70c 100644 --- a/src/webflow/resources/sites/types/sites_publish_response.py +++ b/src/webflow/resources/sites/types/sites_publish_response.py @@ -1,28 +1,25 @@ # This file was auto-generated by Fern from our API Definition. -from ....core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ....types.domain import Domain -from ....core.serialization import FieldMetadata + import pydantic -from ....core.pydantic_utilities import IS_PYDANTIC_V2 +import typing_extensions +from ....core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ....core.serialization import FieldMetadata +from ....types.domain import Domain class SitesPublishResponse(UniversalBaseModel): custom_domains: typing_extensions.Annotated[ - typing.Optional[typing.List[Domain]], FieldMetadata(alias="customDomains") - ] = pydantic.Field(default=None) - """ - Array of domains objects - """ - + typing.Optional[typing.List[Domain]], + FieldMetadata(alias="customDomains"), + pydantic.Field(alias="customDomains", description="Array of domains objects"), + ] = None publish_to_webflow_subdomain: typing_extensions.Annotated[ - typing.Optional[bool], FieldMetadata(alias="publishToWebflowSubdomain") - ] = pydantic.Field(default=None) - """ - Flag for publishing to webflow.io subdomain - """ + typing.Optional[bool], + FieldMetadata(alias="publishToWebflowSubdomain"), + pydantic.Field(alias="publishToWebflowSubdomain", description="Flag for publishing to webflow.io subdomain"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/resources/token/__init__.py b/src/webflow/resources/token/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/token/__init__.py +++ b/src/webflow/resources/token/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/token/client.py b/src/webflow/resources/token/client.py index d8cfd16..d4712d7 100644 --- a/src/webflow/resources/token/client.py +++ b/src/webflow/resources/token/client.py @@ -1,22 +1,28 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.client_wrapper import SyncClientWrapper import typing + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions -from ...types.authorized_user import AuthorizedUser -from ...core.pydantic_utilities import parse_obj_as -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.forbidden_error import ForbiddenError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError from ...types.authorization import Authorization -from ...core.client_wrapper import AsyncClientWrapper +from ...types.authorized_user import AuthorizedUser +from .raw_client import AsyncRawTokenClient, RawTokenClient class TokenClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawTokenClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawTokenClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawTokenClient + """ + return self._raw_client def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = None) -> AuthorizedUser: """ @@ -43,45 +49,8 @@ def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = No ) client.token.authorized_by() """ - _response = self._client_wrapper.httpx_client.request( - "token/authorized_by", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AuthorizedUser, - parse_obj_as( - type_=AuthorizedUser, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.authorized_by(request_options=request_options) + return _response.data def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) -> Authorization: """ @@ -108,40 +77,24 @@ def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) ) client.token.introspect() """ - _response = self._client_wrapper.httpx_client.request( - "token/introspect", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Authorization, - parse_obj_as( - type_=Authorization, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.introspect(request_options=request_options) + return _response.data class AsyncTokenClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawTokenClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawTokenClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawTokenClient + """ + return self._raw_client async def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = None) -> AuthorizedUser: """ @@ -176,45 +129,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "token/authorized_by", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - AuthorizedUser, - parse_obj_as( - type_=AuthorizedUser, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.authorized_by(request_options=request_options) + return _response.data async def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) -> Authorization: """ @@ -249,32 +165,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - "token/introspect", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Authorization, - parse_obj_as( - type_=Authorization, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.introspect(request_options=request_options) + return _response.data diff --git a/src/webflow/resources/token/raw_client.py b/src/webflow/resources/token/raw_client.py new file mode 100644 index 0000000..ea49a25 --- /dev/null +++ b/src/webflow/resources/token/raw_client.py @@ -0,0 +1,261 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...errors.forbidden_error import ForbiddenError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.authorization import Authorization +from ...types.authorized_user import AuthorizedUser +from ...types.error import Error +from pydantic import ValidationError + + +class RawTokenClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def authorized_by(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[AuthorizedUser]: + """ + Information about the Authorized User + + Required Scope | `authorized_user:read` + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[AuthorizedUser] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + "token/authorized_by", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AuthorizedUser, + parse_obj_as( + type_=AuthorizedUser, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def introspect(self, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Authorization]: + """ + Information about the authorization token + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Authorization] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + "token/introspect", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Authorization, + parse_obj_as( + type_=Authorization, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawTokenClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def authorized_by( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[AuthorizedUser]: + """ + Information about the Authorized User + + Required Scope | `authorized_user:read` + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[AuthorizedUser] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + "token/authorized_by", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + AuthorizedUser, + parse_obj_as( + type_=AuthorizedUser, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def introspect( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Authorization]: + """ + Information about the authorization token + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Authorization] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + "token/introspect", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Authorization, + parse_obj_as( + type_=Authorization, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/webhooks/__init__.py b/src/webflow/resources/webhooks/__init__.py index f3ea265..5cde020 100644 --- a/src/webflow/resources/webhooks/__init__.py +++ b/src/webflow/resources/webhooks/__init__.py @@ -1,2 +1,4 @@ # This file was auto-generated by Fern from our API Definition. +# isort: skip_file + diff --git a/src/webflow/resources/webhooks/client.py b/src/webflow/resources/webhooks/client.py index c6821a9..4360526 100644 --- a/src/webflow/resources/webhooks/client.py +++ b/src/webflow/resources/webhooks/client.py @@ -1,25 +1,15 @@ # This file was auto-generated by Fern from our API Definition. +import datetime as dt import typing -from ...core.client_wrapper import SyncClientWrapper + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ...core.request_options import RequestOptions -from ...types.webhook_list import WebhookList -from ...core.jsonable_encoder import jsonable_encoder -from ...core.pydantic_utilities import parse_obj_as -from ...errors.bad_request_error import BadRequestError -from ...errors.unauthorized_error import UnauthorizedError -from ...types.error import Error -from ...errors.not_found_error import NotFoundError -from ...errors.too_many_requests_error import TooManyRequestsError -from ...errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from ...core.api_error import ApiError from ...types.trigger_type import TriggerType -from ...types.webhook_filter import WebhookFilter -import datetime as dt from ...types.webhook import Webhook -from ...core.serialization import convert_and_respect_annotation_metadata -from ...core.client_wrapper import AsyncClientWrapper +from ...types.webhook_filter import WebhookFilter +from ...types.webhook_list import WebhookList +from .raw_client import AsyncRawWebhooksClient, RawWebhooksClient # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -27,7 +17,18 @@ class WebhooksClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawWebhooksClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawWebhooksClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawWebhooksClient + """ + return self._raw_client def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> WebhookList: """ @@ -59,75 +60,8 @@ def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] site_id="580e63e98c9a982ac9b8b741", ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/webhooks", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - WebhookList, - parse_obj_as( - type_=WebhookList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.list(site_id, request_options=request_options) + return _response.data def create( self, @@ -211,88 +145,19 @@ def create( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id_)}/webhooks", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "id": id, - "triggerType": trigger_type, - "url": url, - "workspaceId": workspace_id, - "siteId": site_id, - "filter": convert_and_respect_annotation_metadata( - object_=filter, annotation=WebhookFilter, direction="write" - ), - "lastTriggered": last_triggered, - "createdOn": created_on, - }, + _response = self._raw_client.create( + site_id_, + id=id, + trigger_type=trigger_type, + url=url, + workspace_id=workspace_id, + site_id=site_id, + filter=filter, + last_triggered=last_triggered, + created_on=created_on, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Webhook, - parse_obj_as( - type_=Webhook, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data def get(self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Webhook: """ @@ -324,75 +189,8 @@ def get(self, webhook_id: str, *, request_options: typing.Optional[RequestOption webhook_id="580e64008c9a982ac9b8b754", ) """ - _response = self._client_wrapper.httpx_client.request( - f"webhooks/{jsonable_encoder(webhook_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Webhook, - parse_obj_as( - type_=Webhook, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.get(webhook_id, request_options=request_options) + return _response.data def delete(self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ @@ -423,74 +221,24 @@ def delete(self, webhook_id: str, *, request_options: typing.Optional[RequestOpt webhook_id="580e64008c9a982ac9b8b754", ) """ - _response = self._client_wrapper.httpx_client.request( - f"webhooks/{jsonable_encoder(webhook_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = self._raw_client.delete(webhook_id, request_options=request_options) + return _response.data class AsyncWebhooksClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawWebhooksClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawWebhooksClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawWebhooksClient + """ + return self._raw_client async def list(self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> WebhookList: """ @@ -530,75 +278,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id)}/webhooks", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - WebhookList, - parse_obj_as( - type_=WebhookList, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.list(site_id, request_options=request_options) + return _response.data async def create( self, @@ -689,88 +370,19 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"sites/{jsonable_encoder(site_id_)}/webhooks", - base_url=self._client_wrapper.get_environment().base, - method="POST", - json={ - "id": id, - "triggerType": trigger_type, - "url": url, - "workspaceId": workspace_id, - "siteId": site_id, - "filter": convert_and_respect_annotation_metadata( - object_=filter, annotation=WebhookFilter, direction="write" - ), - "lastTriggered": last_triggered, - "createdOn": created_on, - }, + _response = await self._raw_client.create( + site_id_, + id=id, + trigger_type=trigger_type, + url=url, + workspace_id=workspace_id, + site_id=site_id, + filter=filter, + last_triggered=last_triggered, + created_on=created_on, request_options=request_options, - omit=OMIT, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Webhook, - parse_obj_as( - type_=Webhook, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data async def get(self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Webhook: """ @@ -810,75 +422,8 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"webhooks/{jsonable_encoder(webhook_id)}", - base_url=self._client_wrapper.get_environment().base, - method="GET", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - Webhook, - parse_obj_as( - type_=Webhook, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.get(webhook_id, request_options=request_options) + return _response.data async def delete(self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: """ @@ -917,66 +462,5 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"webhooks/{jsonable_encoder(webhook_id)}", - base_url=self._client_wrapper.get_environment().base, - method="DELETE", - request_options=request_options, - ) - try: - if 200 <= _response.status_code < 300: - return - if _response.status_code == 400: - raise BadRequestError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + _response = await self._raw_client.delete(webhook_id, request_options=request_options) + return _response.data diff --git a/src/webflow/resources/webhooks/raw_client.py b/src/webflow/resources/webhooks/raw_client.py new file mode 100644 index 0000000..ca4462d --- /dev/null +++ b/src/webflow/resources/webhooks/raw_client.py @@ -0,0 +1,932 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +from json.decoder import JSONDecodeError + +from ...core.api_error import ApiError +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ...core.http_response import AsyncHttpResponse, HttpResponse +from ...core.jsonable_encoder import jsonable_encoder +from ...core.parse_error import ParsingError +from ...core.pydantic_utilities import parse_obj_as +from ...core.request_options import RequestOptions +from ...core.serialization import convert_and_respect_annotation_metadata +from ...errors.bad_request_error import BadRequestError +from ...errors.internal_server_error import InternalServerError +from ...errors.not_found_error import NotFoundError +from ...errors.too_many_requests_error import TooManyRequestsError +from ...errors.unauthorized_error import UnauthorizedError +from ...types.error import Error +from ...types.trigger_type import TriggerType +from ...types.webhook import Webhook +from ...types.webhook_filter import WebhookFilter +from ...types.webhook_list import WebhookList +from pydantic import ValidationError + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawWebhooksClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[WebhookList]: + """ + List all App-created Webhooks registered for a given site + + Required scope | `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[WebhookList] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/webhooks", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WebhookList, + parse_obj_as( + type_=WebhookList, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create( + self, + site_id_: str, + *, + id: typing.Optional[str] = OMIT, + trigger_type: typing.Optional[TriggerType] = OMIT, + url: typing.Optional[str] = OMIT, + workspace_id: typing.Optional[str] = OMIT, + site_id: typing.Optional[str] = OMIT, + filter: typing.Optional[WebhookFilter] = OMIT, + last_triggered: typing.Optional[dt.datetime] = OMIT, + created_on: typing.Optional[dt.datetime] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Webhook]: + """ + Create a new Webhook. + + Limit of 75 registrations per `triggerType`, per site. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Required scope | `sites:write` + + Parameters + ---------- + site_id_ : str + Unique identifier for a Site + + id : typing.Optional[str] + Unique identifier for the Webhook registration + + trigger_type : typing.Optional[TriggerType] + + url : typing.Optional[str] + URL to send the Webhook payload to + + workspace_id : typing.Optional[str] + Unique identifier for the Workspace the Webhook is registered in + + site_id : typing.Optional[str] + Unique identifier for the Site the Webhook is registered in + + filter : typing.Optional[WebhookFilter] + Only supported for the `form_submission` trigger type. Filter for the form you want Webhooks to be sent for. + + last_triggered : typing.Optional[dt.datetime] + Date the Webhook instance was last triggered + + created_on : typing.Optional[dt.datetime] + Date the Webhook registration was created + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Webhook] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id_)}/webhooks", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "id": id, + "triggerType": trigger_type, + "url": url, + "workspaceId": workspace_id, + "siteId": site_id, + "filter": convert_and_respect_annotation_metadata( + object_=filter, annotation=WebhookFilter, direction="write" + ), + "lastTriggered": last_triggered, + "createdOn": created_on, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Webhook, + parse_obj_as( + type_=Webhook, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def get(self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Webhook]: + """ + Get a specific Webhook instance + + Required scope: `sites:read` + + Parameters + ---------- + webhook_id : str + Unique identifier for a Webhook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Webhook] + Request was successful + """ + _response = self._client_wrapper.httpx_client.request( + f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Webhook, + parse_obj_as( + type_=Webhook, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete(self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[None]: + """ + Remove a Webhook + + Required scope: `sites:read` + + Parameters + ---------- + webhook_id : str + Unique identifier for a Webhook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawWebhooksClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, site_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[WebhookList]: + """ + List all App-created Webhooks registered for a given site + + Required scope | `sites:read` + + Parameters + ---------- + site_id : str + Unique identifier for a Site + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[WebhookList] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id)}/webhooks", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WebhookList, + parse_obj_as( + type_=WebhookList, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create( + self, + site_id_: str, + *, + id: typing.Optional[str] = OMIT, + trigger_type: typing.Optional[TriggerType] = OMIT, + url: typing.Optional[str] = OMIT, + workspace_id: typing.Optional[str] = OMIT, + site_id: typing.Optional[str] = OMIT, + filter: typing.Optional[WebhookFilter] = OMIT, + last_triggered: typing.Optional[dt.datetime] = OMIT, + created_on: typing.Optional[dt.datetime] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Webhook]: + """ + Create a new Webhook. + + Limit of 75 registrations per `triggerType`, per site. + + Access to this endpoint requires a bearer token from a [Data Client App](/data/docs/getting-started-data-clients). + Required scope | `sites:write` + + Parameters + ---------- + site_id_ : str + Unique identifier for a Site + + id : typing.Optional[str] + Unique identifier for the Webhook registration + + trigger_type : typing.Optional[TriggerType] + + url : typing.Optional[str] + URL to send the Webhook payload to + + workspace_id : typing.Optional[str] + Unique identifier for the Workspace the Webhook is registered in + + site_id : typing.Optional[str] + Unique identifier for the Site the Webhook is registered in + + filter : typing.Optional[WebhookFilter] + Only supported for the `form_submission` trigger type. Filter for the form you want Webhooks to be sent for. + + last_triggered : typing.Optional[dt.datetime] + Date the Webhook instance was last triggered + + created_on : typing.Optional[dt.datetime] + Date the Webhook registration was created + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Webhook] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"sites/{jsonable_encoder(site_id_)}/webhooks", + base_url=self._client_wrapper.get_environment().base, + method="POST", + json={ + "id": id, + "triggerType": trigger_type, + "url": url, + "workspaceId": workspace_id, + "siteId": site_id, + "filter": convert_and_respect_annotation_metadata( + object_=filter, annotation=WebhookFilter, direction="write" + ), + "lastTriggered": last_triggered, + "createdOn": created_on, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Webhook, + parse_obj_as( + type_=Webhook, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def get( + self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Webhook]: + """ + Get a specific Webhook instance + + Required scope: `sites:read` + + Parameters + ---------- + webhook_id : str + Unique identifier for a Webhook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Webhook] + Request was successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Webhook, + parse_obj_as( + type_=Webhook, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete( + self, webhook_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Remove a Webhook + + Required scope: `sites:read` + + Parameters + ---------- + webhook_id : str + Unique identifier for a Webhook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"webhooks/{jsonable_encoder(webhook_id)}", + base_url=self._client_wrapper.get_environment().base, + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/workspaces/__init__.py b/src/webflow/resources/workspaces/__init__.py index d6cc054..dd54dbd 100644 --- a/src/webflow/resources/workspaces/__init__.py +++ b/src/webflow/resources/workspaces/__init__.py @@ -1,10 +1,43 @@ # This file was auto-generated by Fern from our API Definition. -from .resources import ( - AuditLogsGetWorkspaceAuditLogsRequestEventType, - AuditLogsGetWorkspaceAuditLogsRequestSortOrder, - audit_logs, -) +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .resources import ( + AuditLogsGetWorkspaceAuditLogsRequestEventType, + AuditLogsGetWorkspaceAuditLogsRequestSortOrder, + audit_logs, + ) +_dynamic_imports: typing.Dict[str, str] = { + "AuditLogsGetWorkspaceAuditLogsRequestEventType": ".resources", + "AuditLogsGetWorkspaceAuditLogsRequestSortOrder": ".resources", + "audit_logs": ".resources", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "AuditLogsGetWorkspaceAuditLogsRequestEventType", diff --git a/src/webflow/resources/workspaces/client.py b/src/webflow/resources/workspaces/client.py index de70ca5..4b6aa91 100644 --- a/src/webflow/resources/workspaces/client.py +++ b/src/webflow/resources/workspaces/client.py @@ -1,18 +1,63 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.client_wrapper import SyncClientWrapper -from .resources.audit_logs.client import AuditLogsClient -from ...core.client_wrapper import AsyncClientWrapper -from .resources.audit_logs.client import AsyncAuditLogsClient +from __future__ import annotations + +import typing + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .raw_client import AsyncRawWorkspacesClient, RawWorkspacesClient + +if typing.TYPE_CHECKING: + from .resources.audit_logs.client import AsyncAuditLogsClient, AuditLogsClient class WorkspacesClient: def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawWorkspacesClient(client_wrapper=client_wrapper) self._client_wrapper = client_wrapper - self.audit_logs = AuditLogsClient(client_wrapper=self._client_wrapper) + self._audit_logs: typing.Optional[AuditLogsClient] = None + + @property + def with_raw_response(self) -> RawWorkspacesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawWorkspacesClient + """ + return self._raw_client + + @property + def audit_logs(self): + if self._audit_logs is None: + from .resources.audit_logs.client import AuditLogsClient # noqa: E402 + + self._audit_logs = AuditLogsClient(client_wrapper=self._client_wrapper) + return self._audit_logs class AsyncWorkspacesClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawWorkspacesClient(client_wrapper=client_wrapper) self._client_wrapper = client_wrapper - self.audit_logs = AsyncAuditLogsClient(client_wrapper=self._client_wrapper) + self._audit_logs: typing.Optional[AsyncAuditLogsClient] = None + + @property + def with_raw_response(self) -> AsyncRawWorkspacesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawWorkspacesClient + """ + return self._raw_client + + @property + def audit_logs(self): + if self._audit_logs is None: + from .resources.audit_logs.client import AsyncAuditLogsClient # noqa: E402 + + self._audit_logs = AsyncAuditLogsClient(client_wrapper=self._client_wrapper) + return self._audit_logs diff --git a/src/webflow/resources/workspaces/raw_client.py b/src/webflow/resources/workspaces/raw_client.py new file mode 100644 index 0000000..8e98606 --- /dev/null +++ b/src/webflow/resources/workspaces/raw_client.py @@ -0,0 +1,13 @@ +# This file was auto-generated by Fern from our API Definition. + +from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper + + +class RawWorkspacesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + +class AsyncRawWorkspacesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper diff --git a/src/webflow/resources/workspaces/resources/__init__.py b/src/webflow/resources/workspaces/resources/__init__.py index 0e96a0e..a7bfbd2 100644 --- a/src/webflow/resources/workspaces/resources/__init__.py +++ b/src/webflow/resources/workspaces/resources/__init__.py @@ -1,7 +1,43 @@ # This file was auto-generated by Fern from our API Definition. -from . import audit_logs -from .audit_logs import AuditLogsGetWorkspaceAuditLogsRequestEventType, AuditLogsGetWorkspaceAuditLogsRequestSortOrder +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from . import audit_logs + from .audit_logs import ( + AuditLogsGetWorkspaceAuditLogsRequestEventType, + AuditLogsGetWorkspaceAuditLogsRequestSortOrder, + ) +_dynamic_imports: typing.Dict[str, str] = { + "AuditLogsGetWorkspaceAuditLogsRequestEventType": ".audit_logs", + "AuditLogsGetWorkspaceAuditLogsRequestSortOrder": ".audit_logs", + "audit_logs": ".audit_logs", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "AuditLogsGetWorkspaceAuditLogsRequestEventType", diff --git a/src/webflow/resources/workspaces/resources/audit_logs/__init__.py b/src/webflow/resources/workspaces/resources/audit_logs/__init__.py index dab3df1..2e698bb 100644 --- a/src/webflow/resources/workspaces/resources/audit_logs/__init__.py +++ b/src/webflow/resources/workspaces/resources/audit_logs/__init__.py @@ -1,5 +1,37 @@ # This file was auto-generated by Fern from our API Definition. -from .types import AuditLogsGetWorkspaceAuditLogsRequestEventType, AuditLogsGetWorkspaceAuditLogsRequestSortOrder +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import AuditLogsGetWorkspaceAuditLogsRequestEventType, AuditLogsGetWorkspaceAuditLogsRequestSortOrder +_dynamic_imports: typing.Dict[str, str] = { + "AuditLogsGetWorkspaceAuditLogsRequestEventType": ".types", + "AuditLogsGetWorkspaceAuditLogsRequestSortOrder": ".types", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["AuditLogsGetWorkspaceAuditLogsRequestEventType", "AuditLogsGetWorkspaceAuditLogsRequestSortOrder"] diff --git a/src/webflow/resources/workspaces/resources/audit_logs/client.py b/src/webflow/resources/workspaces/resources/audit_logs/client.py index dcbded2..2572f43 100644 --- a/src/webflow/resources/workspaces/resources/audit_logs/client.py +++ b/src/webflow/resources/workspaces/resources/audit_logs/client.py @@ -1,29 +1,30 @@ # This file was auto-generated by Fern from our API Definition. -from .....core.client_wrapper import SyncClientWrapper -import typing -from .types.audit_logs_get_workspace_audit_logs_request_sort_order import AuditLogsGetWorkspaceAuditLogsRequestSortOrder -from .types.audit_logs_get_workspace_audit_logs_request_event_type import AuditLogsGetWorkspaceAuditLogsRequestEventType import datetime as dt +import typing + +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .....core.request_options import RequestOptions from .....types.workspace_audit_log_response import WorkspaceAuditLogResponse -from .....core.jsonable_encoder import jsonable_encoder -from .....core.datetime_utils import serialize_datetime -from .....core.pydantic_utilities import parse_obj_as -from .....errors.unauthorized_error import UnauthorizedError -from .....types.error import Error -from .....errors.forbidden_error import ForbiddenError -from .....errors.not_found_error import NotFoundError -from .....errors.too_many_requests_error import TooManyRequestsError -from .....errors.internal_server_error import InternalServerError -from json.decoder import JSONDecodeError -from .....core.api_error import ApiError -from .....core.client_wrapper import AsyncClientWrapper +from .raw_client import AsyncRawAuditLogsClient, RawAuditLogsClient +from .types.audit_logs_get_workspace_audit_logs_request_event_type import AuditLogsGetWorkspaceAuditLogsRequestEventType +from .types.audit_logs_get_workspace_audit_logs_request_sort_order import AuditLogsGetWorkspaceAuditLogsRequestSortOrder class AuditLogsClient: def __init__(self, *, client_wrapper: SyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = RawAuditLogsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawAuditLogsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawAuditLogsClient + """ + return self._raw_client def get_workspace_audit_logs( self, @@ -98,88 +99,33 @@ def get_workspace_audit_logs( ), ) """ - _response = self._client_wrapper.httpx_client.request( - f"workspaces/{jsonable_encoder(workspace_id_or_slug)}/audit_logs", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "limit": limit, - "offset": offset, - "sortOrder": sort_order, - "eventType": event_type, - "from": serialize_datetime(from_) if from_ is not None else None, - "to": serialize_datetime(to) if to is not None else None, - }, + _response = self._raw_client.get_workspace_audit_logs( + workspace_id_or_slug, + limit=limit, + offset=offset, + sort_order=sort_order, + event_type=event_type, + from_=from_, + to=to, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - WorkspaceAuditLogResponse, - parse_obj_as( - type_=WorkspaceAuditLogResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data class AsyncAuditLogsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): - self._client_wrapper = client_wrapper + self._raw_client = AsyncRawAuditLogsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawAuditLogsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawAuditLogsClient + """ + return self._raw_client async def get_workspace_audit_logs( self, @@ -261,80 +207,14 @@ async def main() -> None: asyncio.run(main()) """ - _response = await self._client_wrapper.httpx_client.request( - f"workspaces/{jsonable_encoder(workspace_id_or_slug)}/audit_logs", - base_url=self._client_wrapper.get_environment().base, - method="GET", - params={ - "limit": limit, - "offset": offset, - "sortOrder": sort_order, - "eventType": event_type, - "from": serialize_datetime(from_) if from_ is not None else None, - "to": serialize_datetime(to) if to is not None else None, - }, + _response = await self._raw_client.get_workspace_audit_logs( + workspace_id_or_slug, + limit=limit, + offset=offset, + sort_order=sort_order, + event_type=event_type, + from_=from_, + to=to, request_options=request_options, ) - try: - if 200 <= _response.status_code < 300: - return typing.cast( - WorkspaceAuditLogResponse, - parse_obj_as( - type_=WorkspaceAuditLogResponse, # type: ignore - object_=_response.json(), - ), - ) - if _response.status_code == 401: - raise UnauthorizedError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 403: - raise ForbiddenError( - typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 404: - raise NotFoundError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 429: - raise TooManyRequestsError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - if _response.status_code == 500: - raise InternalServerError( - typing.cast( - Error, - parse_obj_as( - type_=Error, # type: ignore - object_=_response.json(), - ), - ) - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, body=_response.text) - raise ApiError(status_code=_response.status_code, body=_response_json) + return _response.data diff --git a/src/webflow/resources/workspaces/resources/audit_logs/raw_client.py b/src/webflow/resources/workspaces/resources/audit_logs/raw_client.py new file mode 100644 index 0000000..276afcc --- /dev/null +++ b/src/webflow/resources/workspaces/resources/audit_logs/raw_client.py @@ -0,0 +1,310 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +from json.decoder import JSONDecodeError + +from .....core.api_error import ApiError +from .....core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .....core.datetime_utils import serialize_datetime +from .....core.http_response import AsyncHttpResponse, HttpResponse +from .....core.jsonable_encoder import jsonable_encoder +from .....core.parse_error import ParsingError +from .....core.pydantic_utilities import parse_obj_as +from .....core.request_options import RequestOptions +from .....errors.forbidden_error import ForbiddenError +from .....errors.internal_server_error import InternalServerError +from .....errors.not_found_error import NotFoundError +from .....errors.too_many_requests_error import TooManyRequestsError +from .....errors.unauthorized_error import UnauthorizedError +from .....types.error import Error +from .....types.workspace_audit_log_response import WorkspaceAuditLogResponse +from .types.audit_logs_get_workspace_audit_logs_request_event_type import AuditLogsGetWorkspaceAuditLogsRequestEventType +from .types.audit_logs_get_workspace_audit_logs_request_sort_order import AuditLogsGetWorkspaceAuditLogsRequestSortOrder +from pydantic import ValidationError + + +class RawAuditLogsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get_workspace_audit_logs( + self, + workspace_id_or_slug: str, + *, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + sort_order: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] = None, + event_type: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] = None, + from_: typing.Optional[dt.datetime] = None, + to: typing.Optional[dt.datetime] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[WorkspaceAuditLogResponse]: + """ + Get audit logs for a workspace. + + This endpoint requires an Enterprise workspace and a workspace token with the `workspace_activity:read` scope. Create a workspace token from your workspace dashboard integrations page to use this endpoint. + + Required scope | `workspace_activity:read` + + Parameters + ---------- + workspace_id_or_slug : str + Unique identifier or slug for a Workspace + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + sort_order : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] + Sorts the results by asc or desc + + event_type : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] + The event type to filter by + + from_ : typing.Optional[dt.datetime] + The start date to filter by + + to : typing.Optional[dt.datetime] + The end date to filter by + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[WorkspaceAuditLogResponse] + A list of workspace audit logs + """ + _response = self._client_wrapper.httpx_client.request( + f"workspaces/{jsonable_encoder(workspace_id_or_slug)}/audit_logs", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "limit": limit, + "offset": offset, + "sortOrder": sort_order, + "eventType": event_type, + "from": serialize_datetime(from_) if from_ is not None else None, + "to": serialize_datetime(to) if to is not None else None, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkspaceAuditLogResponse, + parse_obj_as( + type_=WorkspaceAuditLogResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawAuditLogsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get_workspace_audit_logs( + self, + workspace_id_or_slug: str, + *, + limit: typing.Optional[int] = None, + offset: typing.Optional[int] = None, + sort_order: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] = None, + event_type: typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] = None, + from_: typing.Optional[dt.datetime] = None, + to: typing.Optional[dt.datetime] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[WorkspaceAuditLogResponse]: + """ + Get audit logs for a workspace. + + This endpoint requires an Enterprise workspace and a workspace token with the `workspace_activity:read` scope. Create a workspace token from your workspace dashboard integrations page to use this endpoint. + + Required scope | `workspace_activity:read` + + Parameters + ---------- + workspace_id_or_slug : str + Unique identifier or slug for a Workspace + + limit : typing.Optional[int] + Maximum number of records to be returned (max limit: 100) + + offset : typing.Optional[int] + Offset used for pagination if the results have more than limit records + + sort_order : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestSortOrder] + Sorts the results by asc or desc + + event_type : typing.Optional[AuditLogsGetWorkspaceAuditLogsRequestEventType] + The event type to filter by + + from_ : typing.Optional[dt.datetime] + The start date to filter by + + to : typing.Optional[dt.datetime] + The end date to filter by + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[WorkspaceAuditLogResponse] + A list of workspace audit logs + """ + _response = await self._client_wrapper.httpx_client.request( + f"workspaces/{jsonable_encoder(workspace_id_or_slug)}/audit_logs", + base_url=self._client_wrapper.get_environment().base, + method="GET", + params={ + "limit": limit, + "offset": offset, + "sortOrder": sort_order, + "eventType": event_type, + "from": serialize_datetime(from_) if from_ is not None else None, + "to": serialize_datetime(to) if to is not None else None, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + WorkspaceAuditLogResponse, + parse_obj_as( + type_=WorkspaceAuditLogResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 401: + raise UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise ForbiddenError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + Error, + parse_obj_as( + type_=Error, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py b/src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py index 3decf29..c54f614 100644 --- a/src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py +++ b/src/webflow/resources/workspaces/resources/audit_logs/types/__init__.py @@ -1,6 +1,38 @@ # This file was auto-generated by Fern from our API Definition. -from .audit_logs_get_workspace_audit_logs_request_event_type import AuditLogsGetWorkspaceAuditLogsRequestEventType -from .audit_logs_get_workspace_audit_logs_request_sort_order import AuditLogsGetWorkspaceAuditLogsRequestSortOrder +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .audit_logs_get_workspace_audit_logs_request_event_type import AuditLogsGetWorkspaceAuditLogsRequestEventType + from .audit_logs_get_workspace_audit_logs_request_sort_order import AuditLogsGetWorkspaceAuditLogsRequestSortOrder +_dynamic_imports: typing.Dict[str, str] = { + "AuditLogsGetWorkspaceAuditLogsRequestEventType": ".audit_logs_get_workspace_audit_logs_request_event_type", + "AuditLogsGetWorkspaceAuditLogsRequestSortOrder": ".audit_logs_get_workspace_audit_logs_request_sort_order", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = ["AuditLogsGetWorkspaceAuditLogsRequestEventType", "AuditLogsGetWorkspaceAuditLogsRequestSortOrder"] diff --git a/src/webflow/types/__init__.py b/src/webflow/types/__init__.py index 94afb21..88c0cbd 100644 --- a/src/webflow/types/__init__.py +++ b/src/webflow/types/__init__.py @@ -1,300 +1,601 @@ # This file was auto-generated by Fern from our API Definition. -from .application import Application -from .asset import Asset -from .asset_folder import AssetFolder -from .asset_folder_list import AssetFolderList -from .asset_upload import AssetUpload -from .asset_upload_upload_details import AssetUploadUploadDetails -from .asset_variant import AssetVariant -from .assets import Assets -from .authorization import Authorization -from .authorization_authorization import AuthorizationAuthorization -from .authorization_authorization_authorized_to import AuthorizationAuthorizationAuthorizedTo -from .authorized_user import AuthorizedUser -from .bad_request_error_body import BadRequestErrorBody -from .bulk_collection_item import BulkCollectionItem -from .bulk_collection_item_field_data import BulkCollectionItemFieldData -from .collection import Collection -from .collection_item import CollectionItem -from .collection_item_changed import CollectionItemChanged -from .collection_item_created import CollectionItemCreated -from .collection_item_field_data import CollectionItemFieldData -from .collection_item_list import CollectionItemList -from .collection_item_list_no_pagination import CollectionItemListNoPagination -from .collection_item_list_pagination import CollectionItemListPagination -from .collection_item_patch_single import CollectionItemPatchSingle -from .collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData -from .collection_item_post_single import CollectionItemPostSingle -from .collection_item_post_single_field_data import CollectionItemPostSingleFieldData -from .collection_item_published import CollectionItemPublished -from .collection_item_removed import CollectionItemRemoved -from .collection_item_removed_payload import CollectionItemRemovedPayload -from .collection_item_removed_payload_field_data import CollectionItemRemovedPayloadFieldData -from .collection_item_unpublished import CollectionItemUnpublished -from .collection_item_unpublished_payload import CollectionItemUnpublishedPayload -from .collection_item_unpublished_payload_field_data import CollectionItemUnpublishedPayloadFieldData -from .collection_item_with_id_input import CollectionItemWithIdInput -from .collection_item_with_id_input_field_data import CollectionItemWithIdInputFieldData -from .collection_list import CollectionList -from .collection_list_array_item import CollectionListArrayItem -from .comment import Comment -from .comment_payload import CommentPayload -from .comment_payload_author import CommentPayloadAuthor -from .comment_payload_mentioned_users_item import CommentPayloadMentionedUsersItem -from .comment_reply import CommentReply -from .comment_reply_author import CommentReplyAuthor -from .comment_reply_list import CommentReplyList -from .comment_reply_list_pagination import CommentReplyListPagination -from .comment_reply_mentioned_users_item import CommentReplyMentionedUsersItem -from .comment_thread import CommentThread -from .comment_thread_author import CommentThreadAuthor -from .comment_thread_list import CommentThreadList -from .comment_thread_list_pagination import CommentThreadListPagination -from .comment_thread_mentioned_users_item import CommentThreadMentionedUsersItem -from .component import Component -from .component_dom import ComponentDom -from .component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite -from .component_instance_node_property_overrides_write_property_overrides_item import ( - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, -) -from .component_list import ComponentList -from .component_node import ComponentNode -from .component_properties import ComponentProperties -from .component_property import ComponentProperty -from .component_property_type import ComponentPropertyType -from .conflict import Conflict -from .custom_code_block import CustomCodeBlock -from .custom_code_block_type import CustomCodeBlockType -from .custom_code_hosted_response import CustomCodeHostedResponse -from .custom_code_inline_response import CustomCodeInlineResponse -from .custom_role import CustomRole -from .custom_role_audit_log_item import CustomRoleAuditLogItem -from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType -from .dom import Dom -from .domain import Domain -from .domains import Domains -from .ecommerce_settings import EcommerceSettings -from .error import Error -from .error_code import ErrorCode -from .field import Field -from .field_create import FieldCreate -from .field_type import FieldType -from .field_validations import FieldValidations -from .field_validations_additional_properties import FieldValidationsAdditionalProperties -from .field_validations_additional_properties_additional_properties import ( - FieldValidationsAdditionalPropertiesAdditionalProperties, -) -from .forbidden_error_body import ForbiddenErrorBody -from .form import Form -from .form_field import FormField -from .form_field_value import FormFieldValue -from .form_field_value_type import FormFieldValueType -from .form_list import FormList -from .form_response_settings import FormResponseSettings -from .form_submission import FormSubmission -from .form_submission_list import FormSubmissionList -from .form_submission_trigger import FormSubmissionTrigger -from .form_submission_trigger_payload import FormSubmissionTriggerPayload -from .form_submission_trigger_payload_schema_item import FormSubmissionTriggerPayloadSchemaItem -from .form_submission_trigger_payload_schema_item_field_type import FormSubmissionTriggerPayloadSchemaItemFieldType -from .image_node import ImageNode -from .image_node_image import ImageNodeImage -from .invalid_domain import InvalidDomain -from .invalid_scopes import InvalidScopes -from .inventory_item import InventoryItem -from .inventory_item_inventory_type import InventoryItemInventoryType -from .items_list_items_live_request_last_published import ItemsListItemsLiveRequestLastPublished -from .items_list_items_request_last_published import ItemsListItemsRequestLastPublished -from .list_custom_code_blocks import ListCustomCodeBlocks -from .locale import Locale -from .locales import Locales -from .metadata import Metadata -from .metadata_options_item import MetadataOptionsItem -from .new_order import NewOrder -from .no_domains import NoDomains -from .node import ( - Node, - Node_ComponentInstance, - Node_Image, - Node_SearchButton, - Node_Select, - Node_SubmitButton, - Node_Text, - Node_TextInput, -) -from .not_enterprise_plan_site import NotEnterprisePlanSite -from .not_enterprise_plan_workspace import NotEnterprisePlanWorkspace -from .option_field import OptionField -from .order import Order -from .order_address import OrderAddress -from .order_address_japan_type import OrderAddressJapanType -from .order_address_type import OrderAddressType -from .order_billing_address import OrderBillingAddress -from .order_billing_address_japan_type import OrderBillingAddressJapanType -from .order_billing_address_type import OrderBillingAddressType -from .order_customer_info import OrderCustomerInfo -from .order_dispute_last_status import OrderDisputeLastStatus -from .order_download_files_item import OrderDownloadFilesItem -from .order_list import OrderList -from .order_metadata import OrderMetadata -from .order_price import OrderPrice -from .order_purchased_item import OrderPurchasedItem -from .order_purchased_item_variant_image import OrderPurchasedItemVariantImage -from .order_purchased_item_variant_image_file import OrderPurchasedItemVariantImageFile -from .order_purchased_item_variant_image_file_variants_item import OrderPurchasedItemVariantImageFileVariantsItem -from .order_shipping_address import OrderShippingAddress -from .order_shipping_address_japan_type import OrderShippingAddressJapanType -from .order_shipping_address_type import OrderShippingAddressType -from .order_status import OrderStatus -from .order_totals import OrderTotals -from .order_totals_extras_item import OrderTotalsExtrasItem -from .order_totals_extras_item_type import OrderTotalsExtrasItemType -from .page import Page -from .page_created_webhook import PageCreatedWebhook -from .page_created_webhook_payload import PageCreatedWebhookPayload -from .page_deleted_webhook import PageDeletedWebhook -from .page_deleted_webhook_payload import PageDeletedWebhookPayload -from .page_list import PageList -from .page_metadata_updated_webhook import PageMetadataUpdatedWebhook -from .page_metadata_updated_webhook_payload import PageMetadataUpdatedWebhookPayload -from .page_open_graph import PageOpenGraph -from .page_seo import PageSeo -from .pagination import Pagination -from .payload import Payload -from .payload_field_data import PayloadFieldData -from .paypal_details import PaypalDetails -from .product import Product -from .product_and_sk_us import ProductAndSkUs -from .product_and_sk_us_list import ProductAndSkUsList -from .product_field_data import ProductFieldData -from .product_field_data_ec_product_type import ProductFieldDataEcProductType -from .product_field_data_tax_category import ProductFieldDataTaxCategory -from .publish_status import PublishStatus -from .redirect import Redirect -from .redirects import Redirects -from .reference_field import ReferenceField -from .reference_field_metadata import ReferenceFieldMetadata -from .reference_field_type import ReferenceFieldType -from .registered_script_list import RegisteredScriptList -from .robots import Robots -from .robots_rules_item import RobotsRulesItem -from .script_apply import ScriptApply -from .script_apply_list import ScriptApplyList -from .script_apply_location import ScriptApplyLocation -from .scripts import Scripts -from .search_button_node import SearchButtonNode -from .search_button_node_write import SearchButtonNodeWrite -from .select import Select -from .select_node import SelectNode -from .select_node_choices_item import SelectNodeChoicesItem -from .select_node_write_choices_item import SelectNodeWriteChoicesItem -from .setting_change import SettingChange -from .setting_change_audit_log_item import SettingChangeAuditLogItem -from .single_locale_created_payload import SingleLocaleCreatedPayload -from .single_locale_created_payload_field_data import SingleLocaleCreatedPayloadFieldData -from .site import Site -from .site_activity_log_item import SiteActivityLogItem -from .site_activity_log_item_event import SiteActivityLogItemEvent -from .site_activity_log_item_resource_operation import SiteActivityLogItemResourceOperation -from .site_activity_log_item_user import SiteActivityLogItemUser -from .site_activity_log_response import SiteActivityLogResponse -from .site_data_collection_type import SiteDataCollectionType -from .site_membership import SiteMembership -from .site_membership_audit_log_item import SiteMembershipAuditLogItem -from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType -from .site_plan import SitePlan -from .site_plan_id import SitePlanId -from .site_plan_name import SitePlanName -from .site_publish import SitePublish -from .site_publish_payload import SitePublishPayload -from .sites import Sites -from .sku import Sku -from .sku_field_data import SkuFieldData -from .sku_field_data_compare_at_price import SkuFieldDataCompareAtPrice -from .sku_field_data_ec_sku_billing_method import SkuFieldDataEcSkuBillingMethod -from .sku_field_data_ec_sku_subscription_plan import SkuFieldDataEcSkuSubscriptionPlan -from .sku_field_data_ec_sku_subscription_plan_interval import SkuFieldDataEcSkuSubscriptionPlanInterval -from .sku_field_data_ec_sku_subscription_plan_plans_item import SkuFieldDataEcSkuSubscriptionPlanPlansItem -from .sku_field_data_ec_sku_subscription_plan_plans_item_status import SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus -from .sku_field_data_price import SkuFieldDataPrice -from .sku_property_list import SkuPropertyList -from .sku_property_list_enum_item import SkuPropertyListEnumItem -from .sku_value_list import SkuValueList -from .static_field import StaticField -from .static_field_type import StaticFieldType -from .stripe_card import StripeCard -from .stripe_card_brand import StripeCardBrand -from .stripe_card_expires import StripeCardExpires -from .stripe_details import StripeDetails -from .submit_button_node import SubmitButtonNode -from .submit_button_node_write import SubmitButtonNodeWrite -from .text import Text -from .text_input_node import TextInputNode -from .text_input_node_write import TextInputNodeWrite -from .text_node import TextNode -from .text_node_text import TextNodeText -from .text_node_write import TextNodeWrite -from .trigger_type import TriggerType -from .updated_order import UpdatedOrder -from .user_access import UserAccess -from .user_access_audit_log_item import UserAccessAuditLogItem -from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType -from .webhook import Webhook -from .webhook_filter import WebhookFilter -from .webhook_list import WebhookList -from .workspace_audit_log_item import ( - WorkspaceAuditLogItem, - WorkspaceAuditLogItem_CustomRole, - WorkspaceAuditLogItem_SiteMembership, - WorkspaceAuditLogItem_UserAccess, - WorkspaceAuditLogItem_WorkspaceInvitation, - WorkspaceAuditLogItem_WorkspaceMembership, - WorkspaceAuditLogItem_WorkspaceSetting, -) -from .workspace_audit_log_item_actor import WorkspaceAuditLogItemActor -from .workspace_audit_log_item_payload_setting_change_method import WorkspaceAuditLogItemPayloadSettingChangeMethod -from .workspace_audit_log_item_payload_site_membership_granular_access import ( - WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess, -) -from .workspace_audit_log_item_payload_site_membership_method import WorkspaceAuditLogItemPayloadSiteMembershipMethod -from .workspace_audit_log_item_payload_site_membership_site import WorkspaceAuditLogItemPayloadSiteMembershipSite -from .workspace_audit_log_item_payload_site_membership_target_user import ( - WorkspaceAuditLogItemPayloadSiteMembershipTargetUser, -) -from .workspace_audit_log_item_payload_site_membership_user_type import ( - WorkspaceAuditLogItemPayloadSiteMembershipUserType, -) -from .workspace_audit_log_item_payload_user_access_method import WorkspaceAuditLogItemPayloadUserAccessMethod -from .workspace_audit_log_item_payload_workspace_invitation_method import ( - WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod, -) -from .workspace_audit_log_item_payload_workspace_invitation_target_user import ( - WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, -) -from .workspace_audit_log_item_payload_workspace_invitation_target_users_item import ( - WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem, -) -from .workspace_audit_log_item_payload_workspace_invitation_user_type import ( - WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, -) -from .workspace_audit_log_item_payload_workspace_membership_method import ( - WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod, -) -from .workspace_audit_log_item_payload_workspace_membership_target_user import ( - WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, -) -from .workspace_audit_log_item_payload_workspace_membership_user_type import ( - WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType, -) -from .workspace_audit_log_item_workspace import WorkspaceAuditLogItemWorkspace -from .workspace_audit_log_response import WorkspaceAuditLogResponse -from .workspace_invitation import WorkspaceInvitation -from .workspace_invitation_audit_log_item import WorkspaceInvitationAuditLogItem -from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType -from .workspace_membership import WorkspaceMembership -from .workspace_membership_audit_log_item import WorkspaceMembershipAuditLogItem -from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .application import Application + from .asset import Asset + from .asset_folder import AssetFolder + from .asset_folder_list import AssetFolderList + from .asset_upload import AssetUpload + from .asset_upload_upload_details import AssetUploadUploadDetails + from .asset_variant import AssetVariant + from .assets import Assets + from .authorization import Authorization + from .authorization_authorization import AuthorizationAuthorization + from .authorization_authorization_authorized_to import AuthorizationAuthorizationAuthorizedTo + from .authorized_user import AuthorizedUser + from .bad_request_error_body import BadRequestErrorBody + from .bulk_collection_item import BulkCollectionItem + from .bulk_collection_item_field_data import BulkCollectionItemFieldData + from .collection import Collection + from .collection_item import CollectionItem + from .collection_item_changed import CollectionItemChanged + from .collection_item_created import CollectionItemCreated + from .collection_item_field_data import CollectionItemFieldData + from .collection_item_list import CollectionItemList + from .collection_item_list_no_pagination import CollectionItemListNoPagination + from .collection_item_list_pagination import CollectionItemListPagination + from .collection_item_patch_single import CollectionItemPatchSingle + from .collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData + from .collection_item_post_single import CollectionItemPostSingle + from .collection_item_post_single_field_data import CollectionItemPostSingleFieldData + from .collection_item_published import CollectionItemPublished + from .collection_item_removed import CollectionItemRemoved + from .collection_item_removed_payload import CollectionItemRemovedPayload + from .collection_item_removed_payload_field_data import CollectionItemRemovedPayloadFieldData + from .collection_item_unpublished import CollectionItemUnpublished + from .collection_item_unpublished_payload import CollectionItemUnpublishedPayload + from .collection_item_unpublished_payload_field_data import CollectionItemUnpublishedPayloadFieldData + from .collection_item_with_id_input import CollectionItemWithIdInput + from .collection_item_with_id_input_field_data import CollectionItemWithIdInputFieldData + from .collection_list import CollectionList + from .collection_list_array_item import CollectionListArrayItem + from .comment import Comment + from .comment_payload import CommentPayload + from .comment_payload_author import CommentPayloadAuthor + from .comment_payload_mentioned_users_item import CommentPayloadMentionedUsersItem + from .comment_reply import CommentReply + from .comment_reply_author import CommentReplyAuthor + from .comment_reply_list import CommentReplyList + from .comment_reply_list_pagination import CommentReplyListPagination + from .comment_reply_mentioned_users_item import CommentReplyMentionedUsersItem + from .comment_thread import CommentThread + from .comment_thread_author import CommentThreadAuthor + from .comment_thread_list import CommentThreadList + from .comment_thread_list_pagination import CommentThreadListPagination + from .comment_thread_mentioned_users_item import CommentThreadMentionedUsersItem + from .component import Component + from .component_dom import ComponentDom + from .component_instance_node_property_overrides_write import ComponentInstanceNodePropertyOverridesWrite + from .component_instance_node_property_overrides_write_property_overrides_item import ( + ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, + ) + from .component_list import ComponentList + from .component_node import ComponentNode + from .component_properties import ComponentProperties + from .component_property import ComponentProperty + from .component_property_type import ComponentPropertyType + from .conflict import Conflict + from .custom_code_block import CustomCodeBlock + from .custom_code_block_type import CustomCodeBlockType + from .custom_code_hosted_response import CustomCodeHostedResponse + from .custom_code_inline_response import CustomCodeInlineResponse + from .custom_role import CustomRole + from .custom_role_audit_log_item import CustomRoleAuditLogItem + from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType + from .dom import Dom + from .domain import Domain + from .domains import Domains + from .ecommerce_settings import EcommerceSettings + from .error import Error + from .error_code import ErrorCode + from .field import Field + from .field_create import FieldCreate + from .field_type import FieldType + from .field_validations import FieldValidations + from .field_validations_additional_properties import FieldValidationsAdditionalProperties + from .field_validations_additional_properties_additional_properties import ( + FieldValidationsAdditionalPropertiesAdditionalProperties, + ) + from .forbidden_error_body import ForbiddenErrorBody + from .form import Form + from .form_field import FormField + from .form_field_value import FormFieldValue + from .form_field_value_type import FormFieldValueType + from .form_list import FormList + from .form_response_settings import FormResponseSettings + from .form_submission import FormSubmission + from .form_submission_list import FormSubmissionList + from .form_submission_trigger import FormSubmissionTrigger + from .form_submission_trigger_payload import FormSubmissionTriggerPayload + from .form_submission_trigger_payload_schema_item import FormSubmissionTriggerPayloadSchemaItem + from .form_submission_trigger_payload_schema_item_field_type import FormSubmissionTriggerPayloadSchemaItemFieldType + from .image_node import ImageNode + from .image_node_image import ImageNodeImage + from .invalid_domain import InvalidDomain + from .invalid_scopes import InvalidScopes + from .inventory_item import InventoryItem + from .inventory_item_inventory_type import InventoryItemInventoryType + from .items_list_items_live_request_last_published import ItemsListItemsLiveRequestLastPublished + from .items_list_items_request_last_published import ItemsListItemsRequestLastPublished + from .list_custom_code_blocks import ListCustomCodeBlocks + from .locale import Locale + from .locales import Locales + from .metadata import Metadata + from .metadata_options_item import MetadataOptionsItem + from .new_order import NewOrder + from .no_domains import NoDomains + from .node import ( + Node, + Node_ComponentInstance, + Node_Image, + Node_SearchButton, + Node_Select, + Node_SubmitButton, + Node_Text, + Node_TextInput, + ) + from .not_enterprise_plan_site import NotEnterprisePlanSite + from .not_enterprise_plan_workspace import NotEnterprisePlanWorkspace + from .option_field import OptionField + from .order import Order + from .order_address import OrderAddress + from .order_address_japan_type import OrderAddressJapanType + from .order_address_type import OrderAddressType + from .order_billing_address import OrderBillingAddress + from .order_billing_address_japan_type import OrderBillingAddressJapanType + from .order_billing_address_type import OrderBillingAddressType + from .order_customer_info import OrderCustomerInfo + from .order_dispute_last_status import OrderDisputeLastStatus + from .order_download_files_item import OrderDownloadFilesItem + from .order_list import OrderList + from .order_metadata import OrderMetadata + from .order_price import OrderPrice + from .order_purchased_item import OrderPurchasedItem + from .order_purchased_item_variant_image import OrderPurchasedItemVariantImage + from .order_purchased_item_variant_image_file import OrderPurchasedItemVariantImageFile + from .order_purchased_item_variant_image_file_variants_item import OrderPurchasedItemVariantImageFileVariantsItem + from .order_shipping_address import OrderShippingAddress + from .order_shipping_address_japan_type import OrderShippingAddressJapanType + from .order_shipping_address_type import OrderShippingAddressType + from .order_status import OrderStatus + from .order_totals import OrderTotals + from .order_totals_extras_item import OrderTotalsExtrasItem + from .order_totals_extras_item_type import OrderTotalsExtrasItemType + from .page import Page + from .page_created_webhook import PageCreatedWebhook + from .page_created_webhook_payload import PageCreatedWebhookPayload + from .page_deleted_webhook import PageDeletedWebhook + from .page_deleted_webhook_payload import PageDeletedWebhookPayload + from .page_list import PageList + from .page_metadata_updated_webhook import PageMetadataUpdatedWebhook + from .page_metadata_updated_webhook_payload import PageMetadataUpdatedWebhookPayload + from .page_open_graph import PageOpenGraph + from .page_seo import PageSeo + from .pagination import Pagination + from .payload import Payload + from .payload_field_data import PayloadFieldData + from .paypal_details import PaypalDetails + from .product import Product + from .product_and_sk_us import ProductAndSkUs + from .product_and_sk_us_list import ProductAndSkUsList + from .product_field_data import ProductFieldData + from .product_field_data_ec_product_type import ProductFieldDataEcProductType + from .product_field_data_tax_category import ProductFieldDataTaxCategory + from .publish_status import PublishStatus + from .redirect import Redirect + from .redirects import Redirects + from .reference_field import ReferenceField + from .reference_field_metadata import ReferenceFieldMetadata + from .reference_field_type import ReferenceFieldType + from .registered_script_list import RegisteredScriptList + from .robots import Robots + from .robots_rules_item import RobotsRulesItem + from .script_apply import ScriptApply + from .script_apply_list import ScriptApplyList + from .script_apply_location import ScriptApplyLocation + from .scripts import Scripts + from .search_button_node import SearchButtonNode + from .search_button_node_write import SearchButtonNodeWrite + from .select import Select + from .select_node import SelectNode + from .select_node_choices_item import SelectNodeChoicesItem + from .select_node_write_choices_item import SelectNodeWriteChoicesItem + from .setting_change import SettingChange + from .setting_change_audit_log_item import SettingChangeAuditLogItem + from .single_locale_created_payload import SingleLocaleCreatedPayload + from .single_locale_created_payload_field_data import SingleLocaleCreatedPayloadFieldData + from .site import Site + from .site_activity_log_item import SiteActivityLogItem + from .site_activity_log_item_event import SiteActivityLogItemEvent + from .site_activity_log_item_resource_operation import SiteActivityLogItemResourceOperation + from .site_activity_log_item_user import SiteActivityLogItemUser + from .site_activity_log_response import SiteActivityLogResponse + from .site_data_collection_type import SiteDataCollectionType + from .site_membership import SiteMembership + from .site_membership_audit_log_item import SiteMembershipAuditLogItem + from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType + from .site_plan import SitePlan + from .site_plan_id import SitePlanId + from .site_plan_name import SitePlanName + from .site_publish import SitePublish + from .site_publish_payload import SitePublishPayload + from .sites import Sites + from .sku import Sku + from .sku_field_data import SkuFieldData + from .sku_field_data_compare_at_price import SkuFieldDataCompareAtPrice + from .sku_field_data_ec_sku_billing_method import SkuFieldDataEcSkuBillingMethod + from .sku_field_data_ec_sku_subscription_plan import SkuFieldDataEcSkuSubscriptionPlan + from .sku_field_data_ec_sku_subscription_plan_interval import SkuFieldDataEcSkuSubscriptionPlanInterval + from .sku_field_data_ec_sku_subscription_plan_plans_item import SkuFieldDataEcSkuSubscriptionPlanPlansItem + from .sku_field_data_ec_sku_subscription_plan_plans_item_status import ( + SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus, + ) + from .sku_field_data_price import SkuFieldDataPrice + from .sku_property_list import SkuPropertyList + from .sku_property_list_enum_item import SkuPropertyListEnumItem + from .sku_value_list import SkuValueList + from .static_field import StaticField + from .static_field_type import StaticFieldType + from .stripe_card import StripeCard + from .stripe_card_brand import StripeCardBrand + from .stripe_card_expires import StripeCardExpires + from .stripe_details import StripeDetails + from .submit_button_node import SubmitButtonNode + from .submit_button_node_write import SubmitButtonNodeWrite + from .text import Text + from .text_input_node import TextInputNode + from .text_input_node_write import TextInputNodeWrite + from .text_node import TextNode + from .text_node_text import TextNodeText + from .text_node_write import TextNodeWrite + from .trigger_type import TriggerType + from .updated_order import UpdatedOrder + from .user_access import UserAccess + from .user_access_audit_log_item import UserAccessAuditLogItem + from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType + from .webhook import Webhook + from .webhook_filter import WebhookFilter + from .webhook_list import WebhookList + from .workspace_audit_log_item import ( + WorkspaceAuditLogItem, + WorkspaceAuditLogItem_CustomRole, + WorkspaceAuditLogItem_SiteMembership, + WorkspaceAuditLogItem_UserAccess, + WorkspaceAuditLogItem_WorkspaceInvitation, + WorkspaceAuditLogItem_WorkspaceMembership, + WorkspaceAuditLogItem_WorkspaceSetting, + ) + from .workspace_audit_log_item_actor import WorkspaceAuditLogItemActor + from .workspace_audit_log_item_payload_setting_change_method import WorkspaceAuditLogItemPayloadSettingChangeMethod + from .workspace_audit_log_item_payload_site_membership_granular_access import ( + WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess, + ) + from .workspace_audit_log_item_payload_site_membership_method import ( + WorkspaceAuditLogItemPayloadSiteMembershipMethod, + ) + from .workspace_audit_log_item_payload_site_membership_site import WorkspaceAuditLogItemPayloadSiteMembershipSite + from .workspace_audit_log_item_payload_site_membership_target_user import ( + WorkspaceAuditLogItemPayloadSiteMembershipTargetUser, + ) + from .workspace_audit_log_item_payload_site_membership_user_type import ( + WorkspaceAuditLogItemPayloadSiteMembershipUserType, + ) + from .workspace_audit_log_item_payload_user_access_method import WorkspaceAuditLogItemPayloadUserAccessMethod + from .workspace_audit_log_item_payload_workspace_invitation_method import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod, + ) + from .workspace_audit_log_item_payload_workspace_invitation_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, + ) + from .workspace_audit_log_item_payload_workspace_invitation_target_users_item import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem, + ) + from .workspace_audit_log_item_payload_workspace_invitation_user_type import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, + ) + from .workspace_audit_log_item_payload_workspace_membership_method import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod, + ) + from .workspace_audit_log_item_payload_workspace_membership_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, + ) + from .workspace_audit_log_item_payload_workspace_membership_user_type import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType, + ) + from .workspace_audit_log_item_workspace import WorkspaceAuditLogItemWorkspace + from .workspace_audit_log_response import WorkspaceAuditLogResponse + from .workspace_invitation import WorkspaceInvitation + from .workspace_invitation_audit_log_item import WorkspaceInvitationAuditLogItem + from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType + from .workspace_membership import WorkspaceMembership + from .workspace_membership_audit_log_item import WorkspaceMembershipAuditLogItem + from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType +_dynamic_imports: typing.Dict[str, str] = { + "Application": ".application", + "Asset": ".asset", + "AssetFolder": ".asset_folder", + "AssetFolderList": ".asset_folder_list", + "AssetUpload": ".asset_upload", + "AssetUploadUploadDetails": ".asset_upload_upload_details", + "AssetVariant": ".asset_variant", + "Assets": ".assets", + "Authorization": ".authorization", + "AuthorizationAuthorization": ".authorization_authorization", + "AuthorizationAuthorizationAuthorizedTo": ".authorization_authorization_authorized_to", + "AuthorizedUser": ".authorized_user", + "BadRequestErrorBody": ".bad_request_error_body", + "BulkCollectionItem": ".bulk_collection_item", + "BulkCollectionItemFieldData": ".bulk_collection_item_field_data", + "Collection": ".collection", + "CollectionItem": ".collection_item", + "CollectionItemChanged": ".collection_item_changed", + "CollectionItemCreated": ".collection_item_created", + "CollectionItemFieldData": ".collection_item_field_data", + "CollectionItemList": ".collection_item_list", + "CollectionItemListNoPagination": ".collection_item_list_no_pagination", + "CollectionItemListPagination": ".collection_item_list_pagination", + "CollectionItemPatchSingle": ".collection_item_patch_single", + "CollectionItemPatchSingleFieldData": ".collection_item_patch_single_field_data", + "CollectionItemPostSingle": ".collection_item_post_single", + "CollectionItemPostSingleFieldData": ".collection_item_post_single_field_data", + "CollectionItemPublished": ".collection_item_published", + "CollectionItemRemoved": ".collection_item_removed", + "CollectionItemRemovedPayload": ".collection_item_removed_payload", + "CollectionItemRemovedPayloadFieldData": ".collection_item_removed_payload_field_data", + "CollectionItemUnpublished": ".collection_item_unpublished", + "CollectionItemUnpublishedPayload": ".collection_item_unpublished_payload", + "CollectionItemUnpublishedPayloadFieldData": ".collection_item_unpublished_payload_field_data", + "CollectionItemWithIdInput": ".collection_item_with_id_input", + "CollectionItemWithIdInputFieldData": ".collection_item_with_id_input_field_data", + "CollectionList": ".collection_list", + "CollectionListArrayItem": ".collection_list_array_item", + "Comment": ".comment", + "CommentPayload": ".comment_payload", + "CommentPayloadAuthor": ".comment_payload_author", + "CommentPayloadMentionedUsersItem": ".comment_payload_mentioned_users_item", + "CommentReply": ".comment_reply", + "CommentReplyAuthor": ".comment_reply_author", + "CommentReplyList": ".comment_reply_list", + "CommentReplyListPagination": ".comment_reply_list_pagination", + "CommentReplyMentionedUsersItem": ".comment_reply_mentioned_users_item", + "CommentThread": ".comment_thread", + "CommentThreadAuthor": ".comment_thread_author", + "CommentThreadList": ".comment_thread_list", + "CommentThreadListPagination": ".comment_thread_list_pagination", + "CommentThreadMentionedUsersItem": ".comment_thread_mentioned_users_item", + "Component": ".component", + "ComponentDom": ".component_dom", + "ComponentInstanceNodePropertyOverridesWrite": ".component_instance_node_property_overrides_write", + "ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem": ".component_instance_node_property_overrides_write_property_overrides_item", + "ComponentList": ".component_list", + "ComponentNode": ".component_node", + "ComponentProperties": ".component_properties", + "ComponentProperty": ".component_property", + "ComponentPropertyType": ".component_property_type", + "Conflict": ".conflict", + "CustomCodeBlock": ".custom_code_block", + "CustomCodeBlockType": ".custom_code_block_type", + "CustomCodeHostedResponse": ".custom_code_hosted_response", + "CustomCodeInlineResponse": ".custom_code_inline_response", + "CustomRole": ".custom_role", + "CustomRoleAuditLogItem": ".custom_role_audit_log_item", + "CustomRoleAuditLogItemEventSubType": ".custom_role_audit_log_item_event_sub_type", + "Dom": ".dom", + "Domain": ".domain", + "Domains": ".domains", + "EcommerceSettings": ".ecommerce_settings", + "Error": ".error", + "ErrorCode": ".error_code", + "Field": ".field", + "FieldCreate": ".field_create", + "FieldType": ".field_type", + "FieldValidations": ".field_validations", + "FieldValidationsAdditionalProperties": ".field_validations_additional_properties", + "FieldValidationsAdditionalPropertiesAdditionalProperties": ".field_validations_additional_properties_additional_properties", + "ForbiddenErrorBody": ".forbidden_error_body", + "Form": ".form", + "FormField": ".form_field", + "FormFieldValue": ".form_field_value", + "FormFieldValueType": ".form_field_value_type", + "FormList": ".form_list", + "FormResponseSettings": ".form_response_settings", + "FormSubmission": ".form_submission", + "FormSubmissionList": ".form_submission_list", + "FormSubmissionTrigger": ".form_submission_trigger", + "FormSubmissionTriggerPayload": ".form_submission_trigger_payload", + "FormSubmissionTriggerPayloadSchemaItem": ".form_submission_trigger_payload_schema_item", + "FormSubmissionTriggerPayloadSchemaItemFieldType": ".form_submission_trigger_payload_schema_item_field_type", + "ImageNode": ".image_node", + "ImageNodeImage": ".image_node_image", + "InvalidDomain": ".invalid_domain", + "InvalidScopes": ".invalid_scopes", + "InventoryItem": ".inventory_item", + "InventoryItemInventoryType": ".inventory_item_inventory_type", + "ItemsListItemsLiveRequestLastPublished": ".items_list_items_live_request_last_published", + "ItemsListItemsRequestLastPublished": ".items_list_items_request_last_published", + "ListCustomCodeBlocks": ".list_custom_code_blocks", + "Locale": ".locale", + "Locales": ".locales", + "Metadata": ".metadata", + "MetadataOptionsItem": ".metadata_options_item", + "NewOrder": ".new_order", + "NoDomains": ".no_domains", + "Node": ".node", + "Node_ComponentInstance": ".node", + "Node_Image": ".node", + "Node_SearchButton": ".node", + "Node_Select": ".node", + "Node_SubmitButton": ".node", + "Node_Text": ".node", + "Node_TextInput": ".node", + "NotEnterprisePlanSite": ".not_enterprise_plan_site", + "NotEnterprisePlanWorkspace": ".not_enterprise_plan_workspace", + "OptionField": ".option_field", + "Order": ".order", + "OrderAddress": ".order_address", + "OrderAddressJapanType": ".order_address_japan_type", + "OrderAddressType": ".order_address_type", + "OrderBillingAddress": ".order_billing_address", + "OrderBillingAddressJapanType": ".order_billing_address_japan_type", + "OrderBillingAddressType": ".order_billing_address_type", + "OrderCustomerInfo": ".order_customer_info", + "OrderDisputeLastStatus": ".order_dispute_last_status", + "OrderDownloadFilesItem": ".order_download_files_item", + "OrderList": ".order_list", + "OrderMetadata": ".order_metadata", + "OrderPrice": ".order_price", + "OrderPurchasedItem": ".order_purchased_item", + "OrderPurchasedItemVariantImage": ".order_purchased_item_variant_image", + "OrderPurchasedItemVariantImageFile": ".order_purchased_item_variant_image_file", + "OrderPurchasedItemVariantImageFileVariantsItem": ".order_purchased_item_variant_image_file_variants_item", + "OrderShippingAddress": ".order_shipping_address", + "OrderShippingAddressJapanType": ".order_shipping_address_japan_type", + "OrderShippingAddressType": ".order_shipping_address_type", + "OrderStatus": ".order_status", + "OrderTotals": ".order_totals", + "OrderTotalsExtrasItem": ".order_totals_extras_item", + "OrderTotalsExtrasItemType": ".order_totals_extras_item_type", + "Page": ".page", + "PageCreatedWebhook": ".page_created_webhook", + "PageCreatedWebhookPayload": ".page_created_webhook_payload", + "PageDeletedWebhook": ".page_deleted_webhook", + "PageDeletedWebhookPayload": ".page_deleted_webhook_payload", + "PageList": ".page_list", + "PageMetadataUpdatedWebhook": ".page_metadata_updated_webhook", + "PageMetadataUpdatedWebhookPayload": ".page_metadata_updated_webhook_payload", + "PageOpenGraph": ".page_open_graph", + "PageSeo": ".page_seo", + "Pagination": ".pagination", + "Payload": ".payload", + "PayloadFieldData": ".payload_field_data", + "PaypalDetails": ".paypal_details", + "Product": ".product", + "ProductAndSkUs": ".product_and_sk_us", + "ProductAndSkUsList": ".product_and_sk_us_list", + "ProductFieldData": ".product_field_data", + "ProductFieldDataEcProductType": ".product_field_data_ec_product_type", + "ProductFieldDataTaxCategory": ".product_field_data_tax_category", + "PublishStatus": ".publish_status", + "Redirect": ".redirect", + "Redirects": ".redirects", + "ReferenceField": ".reference_field", + "ReferenceFieldMetadata": ".reference_field_metadata", + "ReferenceFieldType": ".reference_field_type", + "RegisteredScriptList": ".registered_script_list", + "Robots": ".robots", + "RobotsRulesItem": ".robots_rules_item", + "ScriptApply": ".script_apply", + "ScriptApplyList": ".script_apply_list", + "ScriptApplyLocation": ".script_apply_location", + "Scripts": ".scripts", + "SearchButtonNode": ".search_button_node", + "SearchButtonNodeWrite": ".search_button_node_write", + "Select": ".select", + "SelectNode": ".select_node", + "SelectNodeChoicesItem": ".select_node_choices_item", + "SelectNodeWriteChoicesItem": ".select_node_write_choices_item", + "SettingChange": ".setting_change", + "SettingChangeAuditLogItem": ".setting_change_audit_log_item", + "SingleLocaleCreatedPayload": ".single_locale_created_payload", + "SingleLocaleCreatedPayloadFieldData": ".single_locale_created_payload_field_data", + "Site": ".site", + "SiteActivityLogItem": ".site_activity_log_item", + "SiteActivityLogItemEvent": ".site_activity_log_item_event", + "SiteActivityLogItemResourceOperation": ".site_activity_log_item_resource_operation", + "SiteActivityLogItemUser": ".site_activity_log_item_user", + "SiteActivityLogResponse": ".site_activity_log_response", + "SiteDataCollectionType": ".site_data_collection_type", + "SiteMembership": ".site_membership", + "SiteMembershipAuditLogItem": ".site_membership_audit_log_item", + "SiteMembershipAuditLogItemEventSubType": ".site_membership_audit_log_item_event_sub_type", + "SitePlan": ".site_plan", + "SitePlanId": ".site_plan_id", + "SitePlanName": ".site_plan_name", + "SitePublish": ".site_publish", + "SitePublishPayload": ".site_publish_payload", + "Sites": ".sites", + "Sku": ".sku", + "SkuFieldData": ".sku_field_data", + "SkuFieldDataCompareAtPrice": ".sku_field_data_compare_at_price", + "SkuFieldDataEcSkuBillingMethod": ".sku_field_data_ec_sku_billing_method", + "SkuFieldDataEcSkuSubscriptionPlan": ".sku_field_data_ec_sku_subscription_plan", + "SkuFieldDataEcSkuSubscriptionPlanInterval": ".sku_field_data_ec_sku_subscription_plan_interval", + "SkuFieldDataEcSkuSubscriptionPlanPlansItem": ".sku_field_data_ec_sku_subscription_plan_plans_item", + "SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus": ".sku_field_data_ec_sku_subscription_plan_plans_item_status", + "SkuFieldDataPrice": ".sku_field_data_price", + "SkuPropertyList": ".sku_property_list", + "SkuPropertyListEnumItem": ".sku_property_list_enum_item", + "SkuValueList": ".sku_value_list", + "StaticField": ".static_field", + "StaticFieldType": ".static_field_type", + "StripeCard": ".stripe_card", + "StripeCardBrand": ".stripe_card_brand", + "StripeCardExpires": ".stripe_card_expires", + "StripeDetails": ".stripe_details", + "SubmitButtonNode": ".submit_button_node", + "SubmitButtonNodeWrite": ".submit_button_node_write", + "Text": ".text", + "TextInputNode": ".text_input_node", + "TextInputNodeWrite": ".text_input_node_write", + "TextNode": ".text_node", + "TextNodeText": ".text_node_text", + "TextNodeWrite": ".text_node_write", + "TriggerType": ".trigger_type", + "UpdatedOrder": ".updated_order", + "UserAccess": ".user_access", + "UserAccessAuditLogItem": ".user_access_audit_log_item", + "UserAccessAuditLogItemEventSubType": ".user_access_audit_log_item_event_sub_type", + "Webhook": ".webhook", + "WebhookFilter": ".webhook_filter", + "WebhookList": ".webhook_list", + "WorkspaceAuditLogItem": ".workspace_audit_log_item", + "WorkspaceAuditLogItemActor": ".workspace_audit_log_item_actor", + "WorkspaceAuditLogItemPayloadSettingChangeMethod": ".workspace_audit_log_item_payload_setting_change_method", + "WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess": ".workspace_audit_log_item_payload_site_membership_granular_access", + "WorkspaceAuditLogItemPayloadSiteMembershipMethod": ".workspace_audit_log_item_payload_site_membership_method", + "WorkspaceAuditLogItemPayloadSiteMembershipSite": ".workspace_audit_log_item_payload_site_membership_site", + "WorkspaceAuditLogItemPayloadSiteMembershipTargetUser": ".workspace_audit_log_item_payload_site_membership_target_user", + "WorkspaceAuditLogItemPayloadSiteMembershipUserType": ".workspace_audit_log_item_payload_site_membership_user_type", + "WorkspaceAuditLogItemPayloadUserAccessMethod": ".workspace_audit_log_item_payload_user_access_method", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod": ".workspace_audit_log_item_payload_workspace_invitation_method", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser": ".workspace_audit_log_item_payload_workspace_invitation_target_user", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem": ".workspace_audit_log_item_payload_workspace_invitation_target_users_item", + "WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType": ".workspace_audit_log_item_payload_workspace_invitation_user_type", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod": ".workspace_audit_log_item_payload_workspace_membership_method", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser": ".workspace_audit_log_item_payload_workspace_membership_target_user", + "WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType": ".workspace_audit_log_item_payload_workspace_membership_user_type", + "WorkspaceAuditLogItemWorkspace": ".workspace_audit_log_item_workspace", + "WorkspaceAuditLogItem_CustomRole": ".workspace_audit_log_item", + "WorkspaceAuditLogItem_SiteMembership": ".workspace_audit_log_item", + "WorkspaceAuditLogItem_UserAccess": ".workspace_audit_log_item", + "WorkspaceAuditLogItem_WorkspaceInvitation": ".workspace_audit_log_item", + "WorkspaceAuditLogItem_WorkspaceMembership": ".workspace_audit_log_item", + "WorkspaceAuditLogItem_WorkspaceSetting": ".workspace_audit_log_item", + "WorkspaceAuditLogResponse": ".workspace_audit_log_response", + "WorkspaceInvitation": ".workspace_invitation", + "WorkspaceInvitationAuditLogItem": ".workspace_invitation_audit_log_item", + "WorkspaceInvitationAuditLogItemEventSubType": ".workspace_invitation_audit_log_item_event_sub_type", + "WorkspaceMembership": ".workspace_membership", + "WorkspaceMembershipAuditLogItem": ".workspace_membership_audit_log_item", + "WorkspaceMembershipAuditLogItemEventSubType": ".workspace_membership_audit_log_item_event_sub_type", +} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + __all__ = [ "Application", diff --git a/src/webflow/types/application.py b/src/webflow/types/application.py index b11f910..2b86757 100644 --- a/src/webflow/types/application.py +++ b/src/webflow/types/application.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Application(UniversalBaseModel): @@ -24,12 +24,11 @@ class Application(UniversalBaseModel): Application homepage URL provided by the developer """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) - """ - Application name provided by the developer - """ + display_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="displayName"), + pydantic.Field(alias="displayName", description="Application name provided by the developer"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/asset.py b/src/webflow/types/asset.py index 8ebad3b..eb3425d 100644 --- a/src/webflow/types/asset.py +++ b/src/webflow/types/asset.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt from .asset_variant import AssetVariant -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Asset(UniversalBaseModel): @@ -20,69 +20,56 @@ class Asset(UniversalBaseModel): Unique identifier for this asset """ - content_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="contentType")] = ( - pydantic.Field(default=None) - ) - """ - File format type - """ - + content_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="contentType"), + pydantic.Field(alias="contentType", description="File format type"), + ] = None size: typing.Optional[int] = pydantic.Field(default=None) """ size in bytes """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - Unique identifier for the site that hosts this asset - """ - - hosted_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="hostedUrl")] = pydantic.Field( - default=None - ) - """ - Link to the asset - """ - - original_file_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="originalFileName")] = ( - pydantic.Field(default=None) - ) - """ - Original file name at the time of upload - """ - - display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() - """ - Display name of the asset - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - Date the asset metadata was last updated - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - Date the asset metadata was created - """ - + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="Unique identifier for the site that hosts this asset"), + ] = None + hosted_url: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="hostedUrl"), + pydantic.Field(alias="hostedUrl", description="Link to the asset"), + ] = None + original_file_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="originalFileName"), + pydantic.Field(alias="originalFileName", description="Original file name at the time of upload"), + ] = None + display_name: typing_extensions.Annotated[ + str, + FieldMetadata(alias="displayName"), + pydantic.Field(alias="displayName", description="Display name of the asset"), + ] + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="Date the asset metadata was last updated"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="Date the asset metadata was created"), + ] = None variants: typing.List[AssetVariant] = pydantic.Field() """ A list of [asset variants](https://help.webflow.com/hc/en-us/articles/33961378697107-Responsive-images) created by Webflow to serve your site responsively. """ - alt_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="altText")] = pydantic.Field( - default=None - ) - """ - The visual description of the asset - """ + alt_text: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="altText"), + pydantic.Field(alias="altText", description="The visual description of the asset"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/asset_folder.py b/src/webflow/types/asset_folder.py index b01747e..193fd69 100644 --- a/src/webflow/types/asset_folder.py +++ b/src/webflow/types/asset_folder.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class AssetFolder(UniversalBaseModel): @@ -19,45 +19,36 @@ class AssetFolder(UniversalBaseModel): Unique identifier for the Asset Folder """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) - """ - User visible name for the Asset Folder - """ - - parent_folder: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="parentFolder")] = ( - pydantic.Field(default=None) - ) - """ - Pointer to parent Asset Folder (or null if root) - """ - + display_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="displayName"), + pydantic.Field(alias="displayName", description="User visible name for the Asset Folder"), + ] = None + parent_folder: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="parentFolder"), + pydantic.Field(alias="parentFolder", description="Pointer to parent Asset Folder (or null if root)"), + ] = None assets: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ Array of Asset instances in the folder """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - The unique ID of the site the Asset Folder belongs to - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - Date that the Asset Folder was created on - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - Date that the Asset Folder was last updated on - """ + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="The unique ID of the site the Asset Folder belongs to"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="Date that the Asset Folder was created on"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="Date that the Asset Folder was last updated on"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/asset_folder_list.py b/src/webflow/types/asset_folder_list.py index 3badf08..e36db60 100644 --- a/src/webflow/types/asset_folder_list.py +++ b/src/webflow/types/asset_folder_list.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .asset_folder import AssetFolder -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata +from .asset_folder import AssetFolder from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class AssetFolderList(UniversalBaseModel): @@ -16,12 +16,10 @@ class AssetFolderList(UniversalBaseModel): """ asset_folders: typing_extensions.Annotated[ - typing.Optional[typing.List[AssetFolder]], FieldMetadata(alias="assetFolders") - ] = pydantic.Field(default=None) - """ - A list of Asset folders - """ - + typing.Optional[typing.List[AssetFolder]], + FieldMetadata(alias="assetFolders"), + pydantic.Field(alias="assetFolders", description="A list of Asset folders"), + ] = None pagination: typing.Optional[Pagination] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/asset_upload.py b/src/webflow/types/asset_upload.py index fe36752..3f02db2 100644 --- a/src/webflow/types/asset_upload.py +++ b/src/webflow/types/asset_upload.py @@ -1,67 +1,61 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions +import datetime as dt import typing -from .asset_upload_upload_details import AssetUploadUploadDetails -from ..core.serialization import FieldMetadata + import pydantic -import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata +from .asset_upload_upload_details import AssetUploadUploadDetails class AssetUpload(UniversalBaseModel): upload_details: typing_extensions.Annotated[ - typing.Optional[AssetUploadUploadDetails], FieldMetadata(alias="uploadDetails") - ] = pydantic.Field(default=None) - """ - Metadata for uploading the asset binary - """ - - content_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="contentType")] = None + typing.Optional[AssetUploadUploadDetails], + FieldMetadata(alias="uploadDetails"), + pydantic.Field(alias="uploadDetails", description="Metadata for uploading the asset binary"), + ] = None + content_type: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="contentType"), pydantic.Field(alias="contentType") + ] = None id: typing.Optional[str] = None - parent_folder: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="parentFolder")] = ( - pydantic.Field(default=None) - ) - """ - Parent folder for the asset - """ - - upload_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="uploadUrl")] = None - asset_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="assetUrl")] = pydantic.Field( - default=None - ) - """ - S3 link to the asset - """ - - hosted_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="hostedUrl")] = pydantic.Field( - default=None - ) - """ - Represents the link to the asset - """ - - original_file_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="originalFileName")] = ( - pydantic.Field(default=None) - ) - """ - Original file name when uploaded. If not specified at time of upload, it may be extracted from the raw file name - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - Date the asset metadata was created - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - Date the asset metadata was last updated - """ + parent_folder: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="parentFolder"), + pydantic.Field(alias="parentFolder", description="Parent folder for the asset"), + ] = None + upload_url: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="uploadUrl"), pydantic.Field(alias="uploadUrl") + ] = None + asset_url: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="assetUrl"), + pydantic.Field(alias="assetUrl", description="S3 link to the asset"), + ] = None + hosted_url: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="hostedUrl"), + pydantic.Field(alias="hostedUrl", description="Represents the link to the asset"), + ] = None + original_file_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="originalFileName"), + pydantic.Field( + alias="originalFileName", + description="Original file name when uploaded. If not specified at time of upload, it may be extracted from the raw file name", + ), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="Date the asset metadata was created"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="Date the asset metadata was last updated"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/asset_upload_upload_details.py b/src/webflow/types/asset_upload_upload_details.py index bf3e115..68e174e 100644 --- a/src/webflow/types/asset_upload_upload_details.py +++ b/src/webflow/types/asset_upload_upload_details.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class AssetUploadUploadDetails(UniversalBaseModel): @@ -15,15 +15,29 @@ class AssetUploadUploadDetails(UniversalBaseModel): acl: typing.Optional[str] = None bucket: typing.Optional[str] = None - x_amz_algorithm: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="X-Amz-Algorithm")] = None - x_amz_credential: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="X-Amz-Credential")] = None - x_amz_date: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="X-Amz-Date")] = None + x_amz_algorithm: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="X-Amz-Algorithm"), pydantic.Field(alias="X-Amz-Algorithm") + ] = None + x_amz_credential: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="X-Amz-Credential"), pydantic.Field(alias="X-Amz-Credential") + ] = None + x_amz_date: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="X-Amz-Date"), pydantic.Field(alias="X-Amz-Date") + ] = None key: typing.Optional[str] = None - policy: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="Policy")] = None - x_amz_signature: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="X-Amz-Signature")] = None + policy: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="Policy"), pydantic.Field(alias="Policy") + ] = None + x_amz_signature: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="X-Amz-Signature"), pydantic.Field(alias="X-Amz-Signature") + ] = None success_action_status: typing.Optional[str] = None - content_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="content-type")] = None - cache_control: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="Cache-Control")] = None + content_type: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="content-type"), pydantic.Field(alias="content-type") + ] = None + cache_control: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="Cache-Control"), pydantic.Field(alias="Cache-Control") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/asset_variant.py b/src/webflow/types/asset_variant.py index 0ad16f1..f43472d 100644 --- a/src/webflow/types/asset_variant.py +++ b/src/webflow/types/asset_variant.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class AssetVariant(UniversalBaseModel): @@ -13,21 +13,21 @@ class AssetVariant(UniversalBaseModel): Asset variant details """ - hosted_url: typing_extensions.Annotated[str, FieldMetadata(alias="hostedUrl")] = pydantic.Field() - """ - URL of where the asset variant is hosted - """ - - original_file_name: typing_extensions.Annotated[str, FieldMetadata(alias="originalFileName")] = pydantic.Field() - """ - Original file name of the variant - """ - - display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() - """ - Display name of the variant - """ - + hosted_url: typing_extensions.Annotated[ + str, + FieldMetadata(alias="hostedUrl"), + pydantic.Field(alias="hostedUrl", description="URL of where the asset variant is hosted"), + ] + original_file_name: typing_extensions.Annotated[ + str, + FieldMetadata(alias="originalFileName"), + pydantic.Field(alias="originalFileName", description="Original file name of the variant"), + ] + display_name: typing_extensions.Annotated[ + str, + FieldMetadata(alias="displayName"), + pydantic.Field(alias="displayName", description="Display name of the variant"), + ] format: str = pydantic.Field() """ format of the variant diff --git a/src/webflow/types/assets.py b/src/webflow/types/assets.py index bd5f8ea..ed33272 100644 --- a/src/webflow/types/assets.py +++ b/src/webflow/types/assets.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .asset import Asset from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class Assets(UniversalBaseModel): diff --git a/src/webflow/types/authorization.py b/src/webflow/types/authorization.py index 7668ace..6deea56 100644 --- a/src/webflow/types/authorization.py +++ b/src/webflow/types/authorization.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .authorization_authorization import AuthorizationAuthorization + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .application import Application -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .authorization_authorization import AuthorizationAuthorization class Authorization(UniversalBaseModel): diff --git a/src/webflow/types/authorization_authorization.py b/src/webflow/types/authorization_authorization.py index b732aac..e3ee7ca 100644 --- a/src/webflow/types/authorization_authorization.py +++ b/src/webflow/types/authorization_authorization.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + import pydantic import typing_extensions -import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .authorization_authorization_authorized_to import AuthorizationAuthorizationAuthorizedTo -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class AuthorizationAuthorization(UniversalBaseModel): @@ -20,41 +20,35 @@ class AuthorizationAuthorization(UniversalBaseModel): The unique ID of the Authorization instance """ - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - The date the Authorization was created - """ - - last_used: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUsed")] = ( - pydantic.Field(default=None) - ) - """ - The date the Authorization was last used - """ - - grant_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="grantType")] = pydantic.Field( - default=None - ) - """ - The grant type of the Authorization - """ - - rate_limit: typing_extensions.Annotated[typing.Optional[int], FieldMetadata(alias="rateLimit")] = pydantic.Field( - default=None - ) - """ - The default rate limit for the Authorization (requests/min) - """ - + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the Authorization was created"), + ] = None + last_used: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUsed"), + pydantic.Field(alias="lastUsed", description="The date the Authorization was last used"), + ] = None + grant_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="grantType"), + pydantic.Field(alias="grantType", description="The grant type of the Authorization"), + ] = None + rate_limit: typing_extensions.Annotated[ + typing.Optional[int], + FieldMetadata(alias="rateLimit"), + pydantic.Field(alias="rateLimit", description="The default rate limit for the Authorization (requests/min)"), + ] = None scope: typing.Optional[str] = pydantic.Field(default=None) """ Comma separted list of OAuth scopes corresponding to the Authorization """ authorized_to: typing_extensions.Annotated[ - typing.Optional[AuthorizationAuthorizationAuthorizedTo], FieldMetadata(alias="authorizedTo") + typing.Optional[AuthorizationAuthorizationAuthorizedTo], + FieldMetadata(alias="authorizedTo"), + pydantic.Field(alias="authorizedTo"), ] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/authorization_authorization_authorized_to.py b/src/webflow/types/authorization_authorization_authorized_to.py index c4316ab..d0189e4 100644 --- a/src/webflow/types/authorization_authorization_authorized_to.py +++ b/src/webflow/types/authorization_authorization_authorized_to.py @@ -1,34 +1,29 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class AuthorizationAuthorizationAuthorizedTo(UniversalBaseModel): site_ids: typing_extensions.Annotated[ - typing.Optional[typing.List[typing.Optional[typing.Any]]], FieldMetadata(alias="siteIds") - ] = pydantic.Field(default=None) - """ - Array of Sites this app is authorized to - """ - + typing.Optional[typing.List[typing.Any]], + FieldMetadata(alias="siteIds"), + pydantic.Field(alias="siteIds", description="Array of Sites this app is authorized to"), + ] = None workspace_ids: typing_extensions.Annotated[ - typing.Optional[typing.List[typing.Optional[typing.Any]]], FieldMetadata(alias="workspaceIds") - ] = pydantic.Field(default=None) - """ - Array of Workspaces this app is authorized to - """ - + typing.Optional[typing.List[typing.Any]], + FieldMetadata(alias="workspaceIds"), + pydantic.Field(alias="workspaceIds", description="Array of Workspaces this app is authorized to"), + ] = None user_ids: typing_extensions.Annotated[ - typing.Optional[typing.List[typing.Optional[typing.Any]]], FieldMetadata(alias="userIds") - ] = pydantic.Field(default=None) - """ - Array of Users this app is authorized to - """ + typing.Optional[typing.List[typing.Any]], + FieldMetadata(alias="userIds"), + pydantic.Field(alias="userIds", description="Array of Users this app is authorized to"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/authorized_user.py b/src/webflow/types/authorized_user.py index d91c8c6..bbbb058 100644 --- a/src/webflow/types/authorized_user.py +++ b/src/webflow/types/authorized_user.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class AuthorizedUser(UniversalBaseModel): @@ -19,19 +19,16 @@ class AuthorizedUser(UniversalBaseModel): The user's email address """ - first_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="firstName")] = pydantic.Field( - default=None - ) - """ - The user's first name - """ - - last_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastName")] = pydantic.Field( - default=None - ) - """ - The user's last name - """ + first_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="firstName"), + pydantic.Field(alias="firstName", description="The user's first name"), + ] = None + last_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastName"), + pydantic.Field(alias="lastName", description="The user's last name"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/bad_request_error_body.py b/src/webflow/types/bad_request_error_body.py index 5c1277c..6403cc4 100644 --- a/src/webflow/types/bad_request_error_body.py +++ b/src/webflow/types/bad_request_error_body.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing + from .invalid_domain import InvalidDomain from .no_domains import NoDomains diff --git a/src/webflow/types/bulk_collection_item.py b/src/webflow/types/bulk_collection_item.py index de8e770..f53e06d 100644 --- a/src/webflow/types/bulk_collection_item.py +++ b/src/webflow/types/bulk_collection_item.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .bulk_collection_item_field_data import BulkCollectionItemFieldData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class BulkCollectionItem(UniversalBaseModel): @@ -20,49 +20,41 @@ class BulkCollectionItem(UniversalBaseModel): """ cms_locale_ids: typing_extensions.Annotated[ - typing.Optional[typing.List[str]], FieldMetadata(alias="cmsLocaleIds") - ] = pydantic.Field(default=None) - """ - Array of identifiers for the locales where the item will be created - """ - - last_published: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastPublished")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last published - """ - - last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last updated - """ - - created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( - default=None - ) - """ - The date the item was created - """ - - is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Item is set to archived - """ - - is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Item is set to draft - """ - + typing.Optional[typing.List[str]], + FieldMetadata(alias="cmsLocaleIds"), + pydantic.Field( + alias="cmsLocaleIds", description="Array of identifiers for the locales where the item will be created" + ), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastPublished"), + pydantic.Field(alias="lastPublished", description="The date the item was last published"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the item was last updated"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the item was created"), + ] = None + is_archived: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isArchived"), + pydantic.Field(alias="isArchived", description="Boolean determining if the Item is set to archived"), + ] = None + is_draft: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isDraft"), + pydantic.Field(alias="isDraft", description="Boolean determining if the Item is set to draft"), + ] = None field_data: typing_extensions.Annotated[ - typing.Optional[BulkCollectionItemFieldData], FieldMetadata(alias="fieldData") + typing.Optional[BulkCollectionItemFieldData], + FieldMetadata(alias="fieldData"), + pydantic.Field(alias="fieldData"), ] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/bulk_collection_item_field_data.py b/src/webflow/types/bulk_collection_item_field_data.py index 9b977a3..f428233 100644 --- a/src/webflow/types/bulk_collection_item_field_data.py +++ b/src/webflow/types/bulk_collection_item_field_data.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class BulkCollectionItemFieldData(UniversalBaseModel): diff --git a/src/webflow/types/collection.py b/src/webflow/types/collection.py index 561a535..1976f76 100644 --- a/src/webflow/types/collection.py +++ b/src/webflow/types/collection.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt +import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import typing -import datetime as dt from .field import Field -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Collection(UniversalBaseModel): @@ -20,35 +20,34 @@ class Collection(UniversalBaseModel): Unique identifier for a Collection """ - display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() - """ - Name given to the Collection - """ - - singular_name: typing_extensions.Annotated[str, FieldMetadata(alias="singularName")] = pydantic.Field() - """ - The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”) - """ - + display_name: typing_extensions.Annotated[ + str, + FieldMetadata(alias="displayName"), + pydantic.Field(alias="displayName", description="Name given to the Collection"), + ] + singular_name: typing_extensions.Annotated[ + str, + FieldMetadata(alias="singularName"), + pydantic.Field( + alias="singularName", + description="The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”)", + ), + ] slug: typing.Optional[str] = pydantic.Field(default=None) """ Slug of Collection in Site URL structure """ - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - The date the collection was created - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the collection was last updated - """ - + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the collection was created"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the collection was last updated"), + ] = None fields: typing.List[Field] = pydantic.Field() """ The list of fields in the Collection diff --git a/src/webflow/types/collection_item.py b/src/webflow/types/collection_item.py index 6551900..832a11c 100644 --- a/src/webflow/types/collection_item.py +++ b/src/webflow/types/collection_item.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .collection_item_field_data import CollectionItemFieldData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItem(UniversalBaseModel): @@ -23,49 +23,39 @@ class CollectionItem(UniversalBaseModel): Unique identifier for the Item """ - cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( - pydantic.Field(default=None) - ) - """ - Identifier for the locale of the CMS item - """ - - last_published: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastPublished")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last published - """ - - last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last updated - """ - - created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( - default=None - ) - """ - The date the item was created - """ - - is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Item is set to archived - """ - - is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Item is set to draft - """ - - field_data: typing_extensions.Annotated[CollectionItemFieldData, FieldMetadata(alias="fieldData")] + cms_locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="cmsLocaleId"), + pydantic.Field(alias="cmsLocaleId", description="Identifier for the locale of the CMS item"), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastPublished"), + pydantic.Field(alias="lastPublished", description="The date the item was last published"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the item was last updated"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the item was created"), + ] = None + is_archived: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isArchived"), + pydantic.Field(alias="isArchived", description="Boolean determining if the Item is set to archived"), + ] = None + is_draft: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isDraft"), + pydantic.Field(alias="isDraft", description="Boolean determining if the Item is set to draft"), + ] = None + field_data: typing_extensions.Annotated[ + CollectionItemFieldData, FieldMetadata(alias="fieldData"), pydantic.Field(alias="fieldData") + ] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/collection_item_changed.py b/src/webflow/types/collection_item_changed.py index 4484722..2586381 100644 --- a/src/webflow/types/collection_item_changed.py +++ b/src/webflow/types/collection_item_changed.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .single_locale_created_payload import SingleLocaleCreatedPayload -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItemChanged(UniversalBaseModel): @@ -15,12 +15,10 @@ class CollectionItemChanged(UniversalBaseModel): """ trigger_type: typing_extensions.Annotated[ - typing.Literal["collection_item_changed"], FieldMetadata(alias="triggerType") - ] = pydantic.Field(default="collection_item_changed") - """ - The type of event that triggered the request - """ - + typing.Literal["collection_item_changed"], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = "collection_item_changed" payload: SingleLocaleCreatedPayload if IS_PYDANTIC_V2: diff --git a/src/webflow/types/collection_item_created.py b/src/webflow/types/collection_item_created.py index bc6233c..0103ed7 100644 --- a/src/webflow/types/collection_item_created.py +++ b/src/webflow/types/collection_item_created.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .single_locale_created_payload import SingleLocaleCreatedPayload -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItemCreated(UniversalBaseModel): @@ -15,12 +15,10 @@ class CollectionItemCreated(UniversalBaseModel): """ trigger_type: typing_extensions.Annotated[ - typing.Literal["collection_item_created"], FieldMetadata(alias="triggerType") - ] = pydantic.Field(default="collection_item_created") - """ - The type of event that triggered the request - """ - + typing.Literal["collection_item_created"], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = "collection_item_created" payload: SingleLocaleCreatedPayload if IS_PYDANTIC_V2: diff --git a/src/webflow/types/collection_item_field_data.py b/src/webflow/types/collection_item_field_data.py index 651dbe8..f531e2e 100644 --- a/src/webflow/types/collection_item_field_data.py +++ b/src/webflow/types/collection_item_field_data.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + class CollectionItemFieldData(UniversalBaseModel): name: str = pydantic.Field() diff --git a/src/webflow/types/collection_item_list.py b/src/webflow/types/collection_item_list.py index a1ff6d9..ee576c5 100644 --- a/src/webflow/types/collection_item_list.py +++ b/src/webflow/types/collection_item_list.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .collection_item import CollectionItem + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .collection_item import CollectionItem from .collection_item_list_pagination import CollectionItemListPagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItemList(UniversalBaseModel): diff --git a/src/webflow/types/collection_item_list_no_pagination.py b/src/webflow/types/collection_item_list_no_pagination.py index 2b3f556..bdd0bcd 100644 --- a/src/webflow/types/collection_item_list_no_pagination.py +++ b/src/webflow/types/collection_item_list_no_pagination.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .collection_item import CollectionItem + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .collection_item import CollectionItem class CollectionItemListNoPagination(UniversalBaseModel): diff --git a/src/webflow/types/collection_item_list_pagination.py b/src/webflow/types/collection_item_list_pagination.py index 5035868..a8f72be 100644 --- a/src/webflow/types/collection_item_list_pagination.py +++ b/src/webflow/types/collection_item_list_pagination.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class CollectionItemListPagination(UniversalBaseModel): diff --git a/src/webflow/types/collection_item_patch_single.py b/src/webflow/types/collection_item_patch_single.py index 17266b0..64b0170 100644 --- a/src/webflow/types/collection_item_patch_single.py +++ b/src/webflow/types/collection_item_patch_single.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .collection_item_patch_single_field_data import CollectionItemPatchSingleFieldData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItemPatchSingle(UniversalBaseModel): @@ -19,50 +19,40 @@ class CollectionItemPatchSingle(UniversalBaseModel): Unique identifier for the Item """ - cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( - pydantic.Field(default=None) - ) - """ - Identifier for the locale of the CMS item - """ - - last_published: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastPublished")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last published - """ - - last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last updated - """ - - created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( - default=None - ) - """ - The date the item was created - """ - - is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Item is set to archived - """ - - is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Item is set to draft - """ - + cms_locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="cmsLocaleId"), + pydantic.Field(alias="cmsLocaleId", description="Identifier for the locale of the CMS item"), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastPublished"), + pydantic.Field(alias="lastPublished", description="The date the item was last published"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the item was last updated"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the item was created"), + ] = None + is_archived: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isArchived"), + pydantic.Field(alias="isArchived", description="Boolean determining if the Item is set to archived"), + ] = None + is_draft: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isDraft"), + pydantic.Field(alias="isDraft", description="Boolean determining if the Item is set to draft"), + ] = None field_data: typing_extensions.Annotated[ - typing.Optional[CollectionItemPatchSingleFieldData], FieldMetadata(alias="fieldData") + typing.Optional[CollectionItemPatchSingleFieldData], + FieldMetadata(alias="fieldData"), + pydantic.Field(alias="fieldData"), ] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/collection_item_patch_single_field_data.py b/src/webflow/types/collection_item_patch_single_field_data.py index 2d5d5f8..f952564 100644 --- a/src/webflow/types/collection_item_patch_single_field_data.py +++ b/src/webflow/types/collection_item_patch_single_field_data.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class CollectionItemPatchSingleFieldData(UniversalBaseModel): diff --git a/src/webflow/types/collection_item_post_single.py b/src/webflow/types/collection_item_post_single.py index 3a9bafa..f58465a 100644 --- a/src/webflow/types/collection_item_post_single.py +++ b/src/webflow/types/collection_item_post_single.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .collection_item_post_single_field_data import CollectionItemPostSingleFieldData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItemPostSingle(UniversalBaseModel): @@ -23,49 +23,39 @@ class CollectionItemPostSingle(UniversalBaseModel): Unique identifier for the Item """ - cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( - pydantic.Field(default=None) - ) - """ - Identifier for the locale of the CMS item - """ - - last_published: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastPublished")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last published - """ - - last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last updated - """ - - created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( - default=None - ) - """ - The date the item was created - """ - - is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Item is in an archived state. - """ - - is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Item is in a draft state. - """ - - field_data: typing_extensions.Annotated[CollectionItemPostSingleFieldData, FieldMetadata(alias="fieldData")] + cms_locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="cmsLocaleId"), + pydantic.Field(alias="cmsLocaleId", description="Identifier for the locale of the CMS item"), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastPublished"), + pydantic.Field(alias="lastPublished", description="The date the item was last published"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the item was last updated"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the item was created"), + ] = None + is_archived: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isArchived"), + pydantic.Field(alias="isArchived", description="Boolean determining if the Item is in an archived state."), + ] = None + is_draft: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isDraft"), + pydantic.Field(alias="isDraft", description="Boolean determining if the Item is in a draft state."), + ] = None + field_data: typing_extensions.Annotated[ + CollectionItemPostSingleFieldData, FieldMetadata(alias="fieldData"), pydantic.Field(alias="fieldData") + ] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/collection_item_post_single_field_data.py b/src/webflow/types/collection_item_post_single_field_data.py index ae86f3b..ba4d35a 100644 --- a/src/webflow/types/collection_item_post_single_field_data.py +++ b/src/webflow/types/collection_item_post_single_field_data.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + class CollectionItemPostSingleFieldData(UniversalBaseModel): name: str = pydantic.Field() diff --git a/src/webflow/types/collection_item_published.py b/src/webflow/types/collection_item_published.py index c315f37..1b9acc0 100644 --- a/src/webflow/types/collection_item_published.py +++ b/src/webflow/types/collection_item_published.py @@ -1,22 +1,20 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .payload import Payload -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItemPublished(UniversalBaseModel): - trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( - pydantic.Field(default=None) - ) - """ - The type of event that triggered the request - """ - + trigger_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = None payload: typing.Optional[Payload] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/collection_item_removed.py b/src/webflow/types/collection_item_removed.py index fb09cd7..5c2af06 100644 --- a/src/webflow/types/collection_item_removed.py +++ b/src/webflow/types/collection_item_removed.py @@ -1,22 +1,20 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .collection_item_removed_payload import CollectionItemRemovedPayload -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItemRemoved(UniversalBaseModel): - trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( - pydantic.Field(default=None) - ) - """ - The type of event that triggered the request - """ - + trigger_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = None payload: typing.Optional[CollectionItemRemovedPayload] = pydantic.Field(default=None) """ The payload of data sent from Webflow diff --git a/src/webflow/types/collection_item_removed_payload.py b/src/webflow/types/collection_item_removed_payload.py index 745cf3c..011fb89 100644 --- a/src/webflow/types/collection_item_removed_payload.py +++ b/src/webflow/types/collection_item_removed_payload.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt from .collection_item_removed_payload_field_data import CollectionItemRemovedPayloadFieldData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItemRemovedPayload(UniversalBaseModel): @@ -20,43 +20,45 @@ class CollectionItemRemovedPayload(UniversalBaseModel): The ID of the collection item that was deleted """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - The ID of the site - """ - - workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( - pydantic.Field(default=None) - ) - """ - The ID of the workspace - """ - - collection_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="collectionId")] = ( - pydantic.Field(default=None) - ) - """ - The ID of the collection - """ - - cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( - pydantic.Field(default=None) - ) - """ - Unique identifier of the CMS locale for this item - """ - - last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( - None - ) - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None - is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None - is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="The ID of the site"), + ] = None + workspace_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="workspaceId"), + pydantic.Field(alias="workspaceId", description="The ID of the workspace"), + ] = None + collection_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="collectionId"), + pydantic.Field(alias="collectionId", description="The ID of the collection"), + ] = None + cms_locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="cmsLocaleId"), + pydantic.Field(alias="cmsLocaleId", description="Unique identifier of the CMS locale for this item"), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished"), pydantic.Field(alias="lastPublished") + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated"), pydantic.Field(alias="lastUpdated") + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="createdOn"), pydantic.Field(alias="createdOn") + ] = None + is_archived: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="isArchived"), pydantic.Field(alias="isArchived") + ] = None + is_draft: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="isDraft"), pydantic.Field(alias="isDraft") + ] = None field_data: typing_extensions.Annotated[ - typing.Optional[CollectionItemRemovedPayloadFieldData], FieldMetadata(alias="fieldData") + typing.Optional[CollectionItemRemovedPayloadFieldData], + FieldMetadata(alias="fieldData"), + pydantic.Field(alias="fieldData"), ] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/collection_item_removed_payload_field_data.py b/src/webflow/types/collection_item_removed_payload_field_data.py index bca5629..048baf4 100644 --- a/src/webflow/types/collection_item_removed_payload_field_data.py +++ b/src/webflow/types/collection_item_removed_payload_field_data.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class CollectionItemRemovedPayloadFieldData(UniversalBaseModel): diff --git a/src/webflow/types/collection_item_unpublished.py b/src/webflow/types/collection_item_unpublished.py index ce23d7f..a9200be 100644 --- a/src/webflow/types/collection_item_unpublished.py +++ b/src/webflow/types/collection_item_unpublished.py @@ -1,22 +1,20 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .collection_item_unpublished_payload import CollectionItemUnpublishedPayload -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItemUnpublished(UniversalBaseModel): - trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( - pydantic.Field(default=None) - ) - """ - The type of event that triggered the request - """ - + trigger_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = None payload: typing.Optional[CollectionItemUnpublishedPayload] = pydantic.Field(default=None) """ The payload of data sent from Webflow diff --git a/src/webflow/types/collection_item_unpublished_payload.py b/src/webflow/types/collection_item_unpublished_payload.py index 7250b24..2867a45 100644 --- a/src/webflow/types/collection_item_unpublished_payload.py +++ b/src/webflow/types/collection_item_unpublished_payload.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt from .collection_item_unpublished_payload_field_data import CollectionItemUnpublishedPayloadFieldData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItemUnpublishedPayload(UniversalBaseModel): @@ -20,43 +20,45 @@ class CollectionItemUnpublishedPayload(UniversalBaseModel): The ID of the collection item that was unpublished """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - The ID of the site - """ - - workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( - pydantic.Field(default=None) - ) - """ - The ID of the workspace - """ - - collection_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="collectionId")] = ( - pydantic.Field(default=None) - ) - """ - The ID of the collection - """ - - cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( - pydantic.Field(default=None) - ) - """ - Unique identifier of the CMS locale for this item - """ - - last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( - None - ) - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None - is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None - is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="The ID of the site"), + ] = None + workspace_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="workspaceId"), + pydantic.Field(alias="workspaceId", description="The ID of the workspace"), + ] = None + collection_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="collectionId"), + pydantic.Field(alias="collectionId", description="The ID of the collection"), + ] = None + cms_locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="cmsLocaleId"), + pydantic.Field(alias="cmsLocaleId", description="Unique identifier of the CMS locale for this item"), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished"), pydantic.Field(alias="lastPublished") + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated"), pydantic.Field(alias="lastUpdated") + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="createdOn"), pydantic.Field(alias="createdOn") + ] = None + is_archived: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="isArchived"), pydantic.Field(alias="isArchived") + ] = None + is_draft: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="isDraft"), pydantic.Field(alias="isDraft") + ] = None field_data: typing_extensions.Annotated[ - typing.Optional[CollectionItemUnpublishedPayloadFieldData], FieldMetadata(alias="fieldData") + typing.Optional[CollectionItemUnpublishedPayloadFieldData], + FieldMetadata(alias="fieldData"), + pydantic.Field(alias="fieldData"), ] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/collection_item_unpublished_payload_field_data.py b/src/webflow/types/collection_item_unpublished_payload_field_data.py index 8ae8719..a2004c1 100644 --- a/src/webflow/types/collection_item_unpublished_payload_field_data.py +++ b/src/webflow/types/collection_item_unpublished_payload_field_data.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class CollectionItemUnpublishedPayloadFieldData(UniversalBaseModel): diff --git a/src/webflow/types/collection_item_with_id_input.py b/src/webflow/types/collection_item_with_id_input.py index df3cd7e..0a1aae2 100644 --- a/src/webflow/types/collection_item_with_id_input.py +++ b/src/webflow/types/collection_item_with_id_input.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic import typing_extensions -import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .collection_item_with_id_input_field_data import CollectionItemWithIdInputFieldData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionItemWithIdInput(UniversalBaseModel): @@ -19,50 +19,40 @@ class CollectionItemWithIdInput(UniversalBaseModel): Unique identifier for the Item """ - cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( - pydantic.Field(default=None) - ) - """ - Identifier for the locale of the CMS item - """ - - last_published: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastPublished")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last published - """ - - last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last updated - """ - - created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( - default=None - ) - """ - The date the item was created - """ - - is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Item is set to archived - """ - - is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Item is set to draft - """ - + cms_locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="cmsLocaleId"), + pydantic.Field(alias="cmsLocaleId", description="Identifier for the locale of the CMS item"), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastPublished"), + pydantic.Field(alias="lastPublished", description="The date the item was last published"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the item was last updated"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the item was created"), + ] = None + is_archived: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isArchived"), + pydantic.Field(alias="isArchived", description="Boolean determining if the Item is set to archived"), + ] = None + is_draft: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isDraft"), + pydantic.Field(alias="isDraft", description="Boolean determining if the Item is set to draft"), + ] = None field_data: typing_extensions.Annotated[ - typing.Optional[CollectionItemWithIdInputFieldData], FieldMetadata(alias="fieldData") + typing.Optional[CollectionItemWithIdInputFieldData], + FieldMetadata(alias="fieldData"), + pydantic.Field(alias="fieldData"), ] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/collection_item_with_id_input_field_data.py b/src/webflow/types/collection_item_with_id_input_field_data.py index 3109eb2..d27ccab 100644 --- a/src/webflow/types/collection_item_with_id_input_field_data.py +++ b/src/webflow/types/collection_item_with_id_input_field_data.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class CollectionItemWithIdInputFieldData(UniversalBaseModel): diff --git a/src/webflow/types/collection_list.py b/src/webflow/types/collection_list.py index a1ac376..bfa7212 100644 --- a/src/webflow/types/collection_list.py +++ b/src/webflow/types/collection_list.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .collection_list_array_item import CollectionListArrayItem + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .collection_list_array_item import CollectionListArrayItem class CollectionList(UniversalBaseModel): diff --git a/src/webflow/types/collection_list_array_item.py b/src/webflow/types/collection_list_array_item.py index 77e518a..035f7e0 100644 --- a/src/webflow/types/collection_list_array_item.py +++ b/src/webflow/types/collection_list_array_item.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt +import typing + import pydantic import typing_extensions -import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CollectionListArrayItem(UniversalBaseModel): @@ -19,38 +19,34 @@ class CollectionListArrayItem(UniversalBaseModel): Unique identifier for a Collection """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) - """ - Name given to the Collection - """ - - singular_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="singularName")] = ( - pydantic.Field(default=None) - ) - """ - The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”) - """ - + display_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="displayName"), + pydantic.Field(alias="displayName", description="Name given to the Collection"), + ] = None + singular_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="singularName"), + pydantic.Field( + alias="singularName", + description="The name of one Item in Collection (e.g. ”Blog Post” if the Collection is called “Blog Posts”)", + ), + ] = None slug: typing.Optional[str] = pydantic.Field(default=None) """ Slug of Collection in Site URL structure """ - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - The date the collection was created - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the collection was last updated - """ + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the collection was created"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the collection was last updated"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/comment.py b/src/webflow/types/comment.py index b5df7e7..743c912 100644 --- a/src/webflow/types/comment.py +++ b/src/webflow/types/comment.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .comment_payload import CommentPayload -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Comment(UniversalBaseModel): @@ -14,13 +14,11 @@ class Comment(UniversalBaseModel): The Webhook payload for when a comment thread or reply is made on a Site """ - trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( - pydantic.Field(default=None) - ) - """ - The type of event that triggered the request - """ - + trigger_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = None payload: typing.Optional[CommentPayload] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/comment_payload.py b/src/webflow/types/comment_payload.py index c6b6a38..8b51391 100644 --- a/src/webflow/types/comment_payload.py +++ b/src/webflow/types/comment_payload.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .comment_payload_author import CommentPayloadAuthor from .comment_payload_mentioned_users_item import CommentPayloadMentionedUsersItem -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CommentPayload(UniversalBaseModel): @@ -15,53 +15,41 @@ class CommentPayload(UniversalBaseModel): The comment webhook payload contains data for the thread and for replies. Check the type to determine if the payload is for a thread or a reply. The webhook payload may be delayed by up to 5 minutes. """ - thread_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="threadId")] = pydantic.Field( - default=None - ) - """ - Unique identifier for the comment thread - """ - - comment_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="commentId")] = pydantic.Field( - default=None - ) - """ - Unique identifier for the comment reply - """ - + thread_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="threadId"), + pydantic.Field(alias="threadId", description="Unique identifier for the comment thread"), + ] = None + comment_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="commentId"), + pydantic.Field(alias="commentId", description="Unique identifier for the comment reply"), + ] = None type: typing.Optional[str] = pydantic.Field(default=None) """ The type of comment payload """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - The site unique identifier - """ - - page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = pydantic.Field( - default=None - ) - """ - The page unique identifier - """ - - locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="localeId")] = pydantic.Field( - default=None - ) - """ - The locale unique identifier - """ - - item_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="itemId")] = pydantic.Field( - default=None - ) - """ - The item unique identifier - """ - + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="The site unique identifier"), + ] = None + page_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="pageId"), + pydantic.Field(alias="pageId", description="The page unique identifier"), + ] = None + locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="localeId"), + pydantic.Field(alias="localeId", description="The locale unique identifier"), + ] = None + item_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="itemId"), + pydantic.Field(alias="itemId", description="The item unique identifier"), + ] = None breakpoint: typing.Optional[str] = pydantic.Field(default=None) """ The breakpoint the comment was left on @@ -77,32 +65,30 @@ class CommentPayload(UniversalBaseModel): The content of the comment reply """ - is_resolved: typing_extensions.Annotated[bool, FieldMetadata(alias="isResolved")] = pydantic.Field() - """ - Boolean determining if the comment thread is resolved - """ - + is_resolved: typing_extensions.Annotated[ + bool, + FieldMetadata(alias="isResolved"), + pydantic.Field(alias="isResolved", description="Boolean determining if the comment thread is resolved"), + ] author: CommentPayloadAuthor mentioned_users: typing_extensions.Annotated[ - typing.List[CommentPayloadMentionedUsersItem], FieldMetadata(alias="mentionedUsers") - ] = pydantic.Field() - """ - List of mentioned users. This is an empty array until email notifications are sent, which can take up to 5 minutes after the comment is created. - """ - - created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( - default=None - ) - """ - The date the item was created - """ - - last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last updated - """ + typing.List[CommentPayloadMentionedUsersItem], + FieldMetadata(alias="mentionedUsers"), + pydantic.Field( + alias="mentionedUsers", + description="List of mentioned users. This is an empty array until email notifications are sent, which can take up to 5 minutes after the comment is created.", + ), + ] + created_on: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the item was created"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the item was last updated"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/comment_payload_author.py b/src/webflow/types/comment_payload_author.py index 04c9ba8..a1f8e03 100644 --- a/src/webflow/types/comment_payload_author.py +++ b/src/webflow/types/comment_payload_author.py @@ -1,19 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import typing class CommentPayloadAuthor(UniversalBaseModel): - user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() - """ - The unique identifier of the author - """ - + user_id: typing_extensions.Annotated[ + str, + FieldMetadata(alias="userId"), + pydantic.Field(alias="userId", description="The unique identifier of the author"), + ] email: str = pydantic.Field() """ Email of the author diff --git a/src/webflow/types/comment_payload_mentioned_users_item.py b/src/webflow/types/comment_payload_mentioned_users_item.py index 7a63d83..d9e46b1 100644 --- a/src/webflow/types/comment_payload_mentioned_users_item.py +++ b/src/webflow/types/comment_payload_mentioned_users_item.py @@ -1,19 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import typing class CommentPayloadMentionedUsersItem(UniversalBaseModel): - user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() - """ - The unique identifier of the mentioned user - """ - + user_id: typing_extensions.Annotated[ + str, + FieldMetadata(alias="userId"), + pydantic.Field(alias="userId", description="The unique identifier of the mentioned user"), + ] email: str = pydantic.Field() """ Email of the user diff --git a/src/webflow/types/comment_reply.py b/src/webflow/types/comment_reply.py index 1017249..e3d258a 100644 --- a/src/webflow/types/comment_reply.py +++ b/src/webflow/types/comment_reply.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import typing from .comment_reply_author import CommentReplyAuthor from .comment_reply_mentioned_users_item import CommentReplyMentionedUsersItem -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CommentReply(UniversalBaseModel): @@ -20,28 +20,22 @@ class CommentReply(UniversalBaseModel): Unique identifier for the comment thread """ - comment_id: typing_extensions.Annotated[str, FieldMetadata(alias="commentId")] = pydantic.Field() - """ - The comment reply unique identifier - """ - - site_id: typing_extensions.Annotated[str, FieldMetadata(alias="siteId")] = pydantic.Field() - """ - The site unique identifier - """ - - page_id: typing_extensions.Annotated[str, FieldMetadata(alias="pageId")] = pydantic.Field() - """ - The page unique identifier - """ - - locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="localeId")] = pydantic.Field( - default=None - ) - """ - The locale unique identifier - """ - + comment_id: typing_extensions.Annotated[ + str, + FieldMetadata(alias="commentId"), + pydantic.Field(alias="commentId", description="The comment reply unique identifier"), + ] + site_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="siteId"), pydantic.Field(alias="siteId", description="The site unique identifier") + ] + page_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="pageId"), pydantic.Field(alias="pageId", description="The page unique identifier") + ] + locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="localeId"), + pydantic.Field(alias="localeId", description="The locale unique identifier"), + ] = None breakpoint: str = pydantic.Field() """ The breakpoint the comment was left on @@ -52,32 +46,30 @@ class CommentReply(UniversalBaseModel): The content of the comment reply """ - is_resolved: typing_extensions.Annotated[bool, FieldMetadata(alias="isResolved")] = pydantic.Field() - """ - Boolean determining if the comment thread is resolved - """ - + is_resolved: typing_extensions.Annotated[ + bool, + FieldMetadata(alias="isResolved"), + pydantic.Field(alias="isResolved", description="Boolean determining if the comment thread is resolved"), + ] author: CommentReplyAuthor mentioned_users: typing_extensions.Annotated[ - typing.Optional[typing.List[CommentReplyMentionedUsersItem]], FieldMetadata(alias="mentionedUsers") - ] = pydantic.Field(default=None) - """ - List of mentioned users is an empty array until email notifications are sent. - """ - - last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the item was last updated - """ - - created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( - default=None - ) - """ - The date the item was created - """ + typing.Optional[typing.List[CommentReplyMentionedUsersItem]], + FieldMetadata(alias="mentionedUsers"), + pydantic.Field( + alias="mentionedUsers", + description="List of mentioned users is an empty array until email notifications are sent.", + ), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the item was last updated"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the item was created"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/comment_reply_author.py b/src/webflow/types/comment_reply_author.py index 7509b7e..71fece2 100644 --- a/src/webflow/types/comment_reply_author.py +++ b/src/webflow/types/comment_reply_author.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + class CommentReplyAuthor(UniversalBaseModel): id: str = pydantic.Field() diff --git a/src/webflow/types/comment_reply_list.py b/src/webflow/types/comment_reply_list.py index c382932..5a4cc7c 100644 --- a/src/webflow/types/comment_reply_list.py +++ b/src/webflow/types/comment_reply_list.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .comment_reply import CommentReply from .comment_reply_list_pagination import CommentReplyListPagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class CommentReplyList(UniversalBaseModel): diff --git a/src/webflow/types/comment_reply_list_pagination.py b/src/webflow/types/comment_reply_list_pagination.py index 48fd7ed..580ee06 100644 --- a/src/webflow/types/comment_reply_list_pagination.py +++ b/src/webflow/types/comment_reply_list_pagination.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + class CommentReplyListPagination(UniversalBaseModel): limit: int = pydantic.Field() diff --git a/src/webflow/types/comment_reply_mentioned_users_item.py b/src/webflow/types/comment_reply_mentioned_users_item.py index 12324d9..7315c20 100644 --- a/src/webflow/types/comment_reply_mentioned_users_item.py +++ b/src/webflow/types/comment_reply_mentioned_users_item.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + class CommentReplyMentionedUsersItem(UniversalBaseModel): id: str = pydantic.Field() diff --git a/src/webflow/types/comment_thread.py b/src/webflow/types/comment_thread.py index 0694916..44f1369 100644 --- a/src/webflow/types/comment_thread.py +++ b/src/webflow/types/comment_thread.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import typing from .comment_thread_author import CommentThreadAuthor from .comment_thread_mentioned_users_item import CommentThreadMentionedUsersItem -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CommentThread(UniversalBaseModel): @@ -20,30 +20,22 @@ class CommentThread(UniversalBaseModel): Unique identifier for the comment thread """ - site_id: typing_extensions.Annotated[str, FieldMetadata(alias="siteId")] = pydantic.Field() - """ - The site unique identifier - """ - - page_id: typing_extensions.Annotated[str, FieldMetadata(alias="pageId")] = pydantic.Field() - """ - The page unique identifier - """ - - locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="localeId")] = pydantic.Field( - default=None - ) - """ - The locale unique identifier - """ - - item_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="itemId")] = pydantic.Field( - default=None - ) - """ - The item unique identifier - """ - + site_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="siteId"), pydantic.Field(alias="siteId", description="The site unique identifier") + ] + page_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="pageId"), pydantic.Field(alias="pageId", description="The page unique identifier") + ] + locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="localeId"), + pydantic.Field(alias="localeId", description="The locale unique identifier"), + ] = None + item_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="itemId"), + pydantic.Field(alias="itemId", description="The item unique identifier"), + ] = None breakpoint: str = pydantic.Field() """ The breakpoint the comment was left on @@ -59,28 +51,30 @@ class CommentThread(UniversalBaseModel): The content of the comment reply """ - is_resolved: typing_extensions.Annotated[bool, FieldMetadata(alias="isResolved")] = pydantic.Field() - """ - Boolean determining if the comment thread is resolved - """ - + is_resolved: typing_extensions.Annotated[ + bool, + FieldMetadata(alias="isResolved"), + pydantic.Field(alias="isResolved", description="Boolean determining if the comment thread is resolved"), + ] author: CommentThreadAuthor mentioned_users: typing_extensions.Annotated[ - typing.List[CommentThreadMentionedUsersItem], FieldMetadata(alias="mentionedUsers") - ] = pydantic.Field() - """ - List of mentioned users. This is an empty array until email notifications are sent, which can take up to 5 minutes after the comment is created. - """ - - created_on: typing_extensions.Annotated[str, FieldMetadata(alias="createdOn")] = pydantic.Field() - """ - The date the item was created - """ - - last_updated: typing_extensions.Annotated[str, FieldMetadata(alias="lastUpdated")] = pydantic.Field() - """ - The date the item was last updated - """ + typing.List[CommentThreadMentionedUsersItem], + FieldMetadata(alias="mentionedUsers"), + pydantic.Field( + alias="mentionedUsers", + description="List of mentioned users. This is an empty array until email notifications are sent, which can take up to 5 minutes after the comment is created.", + ), + ] + created_on: typing_extensions.Annotated[ + str, + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the item was created"), + ] + last_updated: typing_extensions.Annotated[ + str, + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the item was last updated"), + ] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/comment_thread_author.py b/src/webflow/types/comment_thread_author.py index c2f1b1e..00cee01 100644 --- a/src/webflow/types/comment_thread_author.py +++ b/src/webflow/types/comment_thread_author.py @@ -1,19 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import typing class CommentThreadAuthor(UniversalBaseModel): - user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() - """ - The unique identifier of the author - """ - + user_id: typing_extensions.Annotated[ + str, + FieldMetadata(alias="userId"), + pydantic.Field(alias="userId", description="The unique identifier of the author"), + ] email: str = pydantic.Field() """ Email of the author diff --git a/src/webflow/types/comment_thread_list.py b/src/webflow/types/comment_thread_list.py index f46e6bd..1b3db57 100644 --- a/src/webflow/types/comment_thread_list.py +++ b/src/webflow/types/comment_thread_list.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .comment_thread import CommentThread from .comment_thread_list_pagination import CommentThreadListPagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class CommentThreadList(UniversalBaseModel): diff --git a/src/webflow/types/comment_thread_list_pagination.py b/src/webflow/types/comment_thread_list_pagination.py index 6b1dccb..e1e22fe 100644 --- a/src/webflow/types/comment_thread_list_pagination.py +++ b/src/webflow/types/comment_thread_list_pagination.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + class CommentThreadListPagination(UniversalBaseModel): limit: int = pydantic.Field() diff --git a/src/webflow/types/comment_thread_mentioned_users_item.py b/src/webflow/types/comment_thread_mentioned_users_item.py index f9a20df..124037a 100644 --- a/src/webflow/types/comment_thread_mentioned_users_item.py +++ b/src/webflow/types/comment_thread_mentioned_users_item.py @@ -1,19 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import typing class CommentThreadMentionedUsersItem(UniversalBaseModel): - user_id: typing_extensions.Annotated[str, FieldMetadata(alias="userId")] = pydantic.Field() - """ - The unique identifier of the mentioned user - """ - + user_id: typing_extensions.Annotated[ + str, + FieldMetadata(alias="userId"), + pydantic.Field(alias="userId", description="The unique identifier of the mentioned user"), + ] email: str = pydantic.Field() """ Email of the user diff --git a/src/webflow/types/component.py b/src/webflow/types/component.py index ae6fea2..51f3d72 100644 --- a/src/webflow/types/component.py +++ b/src/webflow/types/component.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class Component(UniversalBaseModel): diff --git a/src/webflow/types/component_dom.py b/src/webflow/types/component_dom.py index 2f70fc4..5c2d621 100644 --- a/src/webflow/types/component_dom.py +++ b/src/webflow/types/component_dom.py @@ -1,27 +1,25 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .node import Node from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class ComponentDom(UniversalBaseModel): """ - The Component DOM schema represents the content structure of a component. Similar to Page DOM, it captures various content nodes and their associated attributes, but specifically for a component's structure. Each node has a unique identifier and can contain text, images, select or text inputs, submit buttons, or nested component instances. - """ - - component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = ( - pydantic.Field(default=None) - ) - """ - Component ID + The Component DOM schema represents the content structure of a component. Similar to Page DOM, it captures various content nodes and their associated attributes, but specifically for a component's structure. Each node has a unique identifier and can contain text, images, select or text inputs, submit buttons, or nested component instances. """ + component_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="componentId"), + pydantic.Field(alias="componentId", description="Component ID"), + ] = None nodes: typing.Optional[typing.List[Node]] = None pagination: typing.Optional[Pagination] = None diff --git a/src/webflow/types/component_instance_node_property_overrides_write.py b/src/webflow/types/component_instance_node_property_overrides_write.py index 6c7d69c..ddcf2cb 100644 --- a/src/webflow/types/component_instance_node_property_overrides_write.py +++ b/src/webflow/types/component_instance_node_property_overrides_write.py @@ -1,14 +1,14 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -import typing from .component_instance_node_property_overrides_write_property_overrides_item import ( ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem, ) -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class ComponentInstanceNodePropertyOverridesWrite(UniversalBaseModel): @@ -16,18 +16,17 @@ class ComponentInstanceNodePropertyOverridesWrite(UniversalBaseModel): Update text property overrides of a component instance """ - node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() - """ - Node UUID - """ - + node_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="nodeId"), pydantic.Field(alias="nodeId", description="Node UUID") + ] property_overrides: typing_extensions.Annotated[ typing.List[ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem], FieldMetadata(alias="propertyOverrides"), - ] = pydantic.Field() - """ - A list of component instance properties to override within the specified secondary locale. - """ + pydantic.Field( + alias="propertyOverrides", + description="A list of component instance properties to override within the specified secondary locale.", + ), + ] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/component_instance_node_property_overrides_write_property_overrides_item.py b/src/webflow/types/component_instance_node_property_overrides_write_property_overrides_item.py index 313b0d6..13e1256 100644 --- a/src/webflow/types/component_instance_node_property_overrides_write_property_overrides_item.py +++ b/src/webflow/types/component_instance_node_property_overrides_write_property_overrides_item.py @@ -1,24 +1,24 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import typing class ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem(UniversalBaseModel): - property_id: typing_extensions.Annotated[str, FieldMetadata(alias="propertyId")] = pydantic.Field() - """ - The ID of the property. - """ - + property_id: typing_extensions.Annotated[ + str, + FieldMetadata(alias="propertyId"), + pydantic.Field(alias="propertyId", description="The ID of the property."), + ] text: str = pydantic.Field() """ - The new string or HTML value used to override the component instance property value. - The provided value must be compatible with the type of the component instance property. - For example, attempting to override a single-line plain-text property with a multi-line + The new string or HTML value used to override the component instance property value. + The provided value must be compatible with the type of the component instance property. + For example, attempting to override a single-line plain-text property with a multi-line value will result in an error. """ diff --git a/src/webflow/types/component_list.py b/src/webflow/types/component_list.py index cd16188..de17894 100644 --- a/src/webflow/types/component_list.py +++ b/src/webflow/types/component_list.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .component import Component from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class ComponentList(UniversalBaseModel): diff --git a/src/webflow/types/component_node.py b/src/webflow/types/component_node.py index 6735289..d091d2a 100644 --- a/src/webflow/types/component_node.py +++ b/src/webflow/types/component_node.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import typing from .component_property import ComponentProperty -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class ComponentNode(UniversalBaseModel): @@ -19,17 +19,19 @@ class ComponentNode(UniversalBaseModel): The unique identifier of the component instance node """ - component_id: typing_extensions.Annotated[str, FieldMetadata(alias="componentId")] = pydantic.Field() - """ - The unique identifier of the component - """ - + component_id: typing_extensions.Annotated[ + str, + FieldMetadata(alias="componentId"), + pydantic.Field(alias="componentId", description="The unique identifier of the component"), + ] property_overrides: typing_extensions.Annotated[ - typing.List[ComponentProperty], FieldMetadata(alias="propertyOverrides") - ] = pydantic.Field() - """ - List of component properties with overrides for a component instance. - """ + typing.List[ComponentProperty], + FieldMetadata(alias="propertyOverrides"), + pydantic.Field( + alias="propertyOverrides", + description="List of component properties with overrides for a component instance.", + ), + ] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/component_properties.py b/src/webflow/types/component_properties.py index f37e71b..aa97a9c 100644 --- a/src/webflow/types/component_properties.py +++ b/src/webflow/types/component_properties.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .component_property import ComponentProperty from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class ComponentProperties(UniversalBaseModel): @@ -15,13 +15,11 @@ class ComponentProperties(UniversalBaseModel): The Component Properties schema represents a list of properties that store text content. Each property has a unique identifier and can be of different types like plain text or rich text. The schema also provides pagination details for scenarios where there more properties than the limit. """ - component_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="componentId")] = ( - pydantic.Field(default=None) - ) - """ - Component ID - """ - + component_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="componentId"), + pydantic.Field(alias="componentId", description="Component ID"), + ] = None properties: typing.Optional[typing.List[ComponentProperty]] = None pagination: typing.Optional[Pagination] = None diff --git a/src/webflow/types/component_property.py b/src/webflow/types/component_property.py index 7f09d8e..4583f4d 100644 --- a/src/webflow/types/component_property.py +++ b/src/webflow/types/component_property.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .component_property_type import ComponentPropertyType from .text import Text -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class ComponentProperty(UniversalBaseModel): @@ -15,13 +15,11 @@ class ComponentProperty(UniversalBaseModel): Represents a property of a component instance in the DOM. A property contains a list of both the raw text and the HTML representation, allowing for flexibility in rendering and processing. Additional attributes can be associated with the text for styling or other purposes. """ - property_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="propertyId")] = pydantic.Field( - default=None - ) - """ - The ID of the property. - """ - + property_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="propertyId"), + pydantic.Field(alias="propertyId", description="The ID of the property."), + ] = None type: typing.Optional[ComponentPropertyType] = pydantic.Field(default=None) """ The type of the property. diff --git a/src/webflow/types/conflict.py b/src/webflow/types/conflict.py index 30b9809..f90bc65 100644 --- a/src/webflow/types/conflict.py +++ b/src/webflow/types/conflict.py @@ -2,4 +2,4 @@ import typing -Conflict = typing.Optional[typing.Any] +Conflict = typing.Any diff --git a/src/webflow/types/custom_code_block.py b/src/webflow/types/custom_code_block.py index f52e4b8..ea8c8fb 100644 --- a/src/webflow/types/custom_code_block.py +++ b/src/webflow/types/custom_code_block.py @@ -1,14 +1,14 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions +import datetime as dt import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .custom_code_block_type import CustomCodeBlockType from .scripts import Scripts -import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CustomCodeBlock(UniversalBaseModel): @@ -16,39 +16,32 @@ class CustomCodeBlock(UniversalBaseModel): A specific instance of Custom Code applied to a Site or Page """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - The Site ID where the custom code was applied - """ - - page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = pydantic.Field( - default=None - ) - """ - The Page ID (if applied at Page-level) - """ - + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="The Site ID where the custom code was applied"), + ] = None + page_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="pageId"), + pydantic.Field(alias="pageId", description="The Page ID (if applied at Page-level)"), + ] = None type: typing.Optional[CustomCodeBlockType] = pydantic.Field(default=None) """ Whether the Custom Code script is applied at the Site-level or Page-level """ scripts: typing.Optional[Scripts] = None - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - The date the Block was created - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the Block was most recently updated - """ + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the Block was created"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the Block was most recently updated"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/custom_code_hosted_response.py b/src/webflow/types/custom_code_hosted_response.py index 9bc97cf..ddc3bab 100644 --- a/src/webflow/types/custom_code_hosted_response.py +++ b/src/webflow/types/custom_code_hosted_response.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CustomCodeHostedResponse(UniversalBaseModel): @@ -18,48 +18,44 @@ class CustomCodeHostedResponse(UniversalBaseModel): Human readable id, derived from the user-specified display name """ - can_copy: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="canCopy")] = pydantic.Field( - default=None - ) - """ - Define whether the script can be copied on site duplication and transfer - """ - - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) - """ - User-facing name for the script. Must be between 1 and 50 alphanumeric characters - """ - - hosted_location: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="hostedLocation")] = ( - pydantic.Field(default=None) - ) - """ - URI for an externally hosted script location - """ - - integrity_hash: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="integrityHash")] = ( - pydantic.Field(default=None) - ) - """ - Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) - """ - - created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( - default=None - ) - """ - Timestamp when the script version was created - """ - - last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - Timestamp when the script version was last updated - """ - + can_copy: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="canCopy"), + pydantic.Field( + alias="canCopy", description="Define whether the script can be copied on site duplication and transfer" + ), + ] = None + display_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="displayName"), + pydantic.Field( + alias="displayName", + description="User-facing name for the script. Must be between 1 and 50 alphanumeric characters", + ), + ] = None + hosted_location: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="hostedLocation"), + pydantic.Field(alias="hostedLocation", description="URI for an externally hosted script location"), + ] = None + integrity_hash: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="integrityHash"), + pydantic.Field( + alias="integrityHash", + description="Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation)", + ), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="Timestamp when the script version was created"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="Timestamp when the script version was last updated"), + ] = None version: typing.Optional[str] = pydantic.Field(default=None) """ A Semantic Version (SemVer) string, denoting the version of the script diff --git a/src/webflow/types/custom_code_inline_response.py b/src/webflow/types/custom_code_inline_response.py index 7934ec5..971d0d1 100644 --- a/src/webflow/types/custom_code_inline_response.py +++ b/src/webflow/types/custom_code_inline_response.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class CustomCodeInlineResponse(UniversalBaseModel): @@ -18,48 +18,44 @@ class CustomCodeInlineResponse(UniversalBaseModel): Human readable id, derived from the user-specified display name """ - can_copy: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="canCopy")] = pydantic.Field( - default=None - ) - """ - Define whether the script can be copied on site duplication and transfer - """ - - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) - """ - User-facing name for the script. Must be between 1 and 50 alphanumeric characters - """ - - hosted_location: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="hostedLocation")] = ( - pydantic.Field(default=None) - ) - """ - URI for an externally hosted script location - """ - - integrity_hash: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="integrityHash")] = ( - pydantic.Field(default=None) - ) - """ - Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation) - """ - - created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( - default=None - ) - """ - Timestamp when the script version was created - """ - - last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - Timestamp when the script version was last updated - """ - + can_copy: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="canCopy"), + pydantic.Field( + alias="canCopy", description="Define whether the script can be copied on site duplication and transfer" + ), + ] = None + display_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="displayName"), + pydantic.Field( + alias="displayName", + description="User-facing name for the script. Must be between 1 and 50 alphanumeric characters", + ), + ] = None + hosted_location: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="hostedLocation"), + pydantic.Field(alias="hostedLocation", description="URI for an externally hosted script location"), + ] = None + integrity_hash: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="integrityHash"), + pydantic.Field( + alias="integrityHash", + description="Sub-Resource Integrity Hash. Only required for externally hosted scripts (passed via hostedLocation)", + ), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="Timestamp when the script version was created"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="Timestamp when the script version was last updated"), + ] = None version: typing.Optional[str] = pydantic.Field(default=None) """ A Semantic Version (SemVer) string, denoting the version of the script diff --git a/src/webflow/types/custom_role.py b/src/webflow/types/custom_role.py index f8c9440..5c45925 100644 --- a/src/webflow/types/custom_role.py +++ b/src/webflow/types/custom_role.py @@ -1,27 +1,24 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class CustomRole(UniversalBaseModel): - role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( - default=None - ) - """ - The name of the custom role - """ - - previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( - pydantic.Field(default=None) - ) - """ - The previous name of the custom role - """ + role_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="roleName"), + pydantic.Field(alias="roleName", description="The name of the custom role"), + ] = None + previous_role_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="previousRoleName"), + pydantic.Field(alias="previousRoleName", description="The previous name of the custom role"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/custom_role_audit_log_item.py b/src/webflow/types/custom_role_audit_log_item.py index 336aa26..79938a2 100644 --- a/src/webflow/types/custom_role_audit_log_item.py +++ b/src/webflow/types/custom_role_audit_log_item.py @@ -1,18 +1,20 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .custom_role import CustomRole -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic +from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType class CustomRoleAuditLogItem(UniversalBaseModel): event_sub_type: typing_extensions.Annotated[ - typing.Optional[CustomRoleAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + typing.Optional[CustomRoleAuditLogItemEventSubType], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[CustomRole] = None diff --git a/src/webflow/types/dom.py b/src/webflow/types/dom.py index 45c87b4..fe23cac 100644 --- a/src/webflow/types/dom.py +++ b/src/webflow/types/dom.py @@ -1,14 +1,14 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions +import datetime as dt import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .node import Node from .pagination import Pagination -import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Dom(UniversalBaseModel): @@ -16,28 +16,24 @@ class Dom(UniversalBaseModel): The DOM (Document Object Model) schema represents the content structure of a web page or component. It captures various content nodes along with their associated attributes. Each node has a unique identifier and can be of different types like text, image or component-instance. The schema also provides pagination details for scenarios where the content nodes are too many to be fetched in a single request. """ - page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = pydantic.Field( - default=None - ) - """ - Page ID - """ - - branch_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="branchId")] = pydantic.Field( - default=None - ) - """ - The unique identifier of a [specific page branch.](https://help.webflow.com/hc/en-us/articles/33961355506195-Page-branching) - """ - + page_id: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="pageId"), pydantic.Field(alias="pageId", description="Page ID") + ] = None + branch_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="branchId"), + pydantic.Field( + alias="branchId", + description="The unique identifier of a [specific page branch.](https://help.webflow.com/hc/en-us/articles/33961355506195-Page-branching)", + ), + ] = None nodes: typing.Optional[typing.List[Node]] = None pagination: typing.Optional[Pagination] = None - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the page dom was most recently updated - """ + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the page dom was most recently updated"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/domain.py b/src/webflow/types/domain.py index e678d1d..b82a1fd 100644 --- a/src/webflow/types/domain.py +++ b/src/webflow/types/domain.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic +import datetime as dt import typing + +import pydantic import typing_extensions -import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Domain(UniversalBaseModel): @@ -20,12 +20,11 @@ class Domain(UniversalBaseModel): The registered Domain name """ - last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( - pydantic.Field(default=None) - ) - """ - The date the custom domain was last published to - """ + last_published: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastPublished"), + pydantic.Field(alias="lastPublished", description="The date the custom domain was last published to"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/domains.py b/src/webflow/types/domains.py index c34d85b..959efa0 100644 --- a/src/webflow/types/domains.py +++ b/src/webflow/types/domains.py @@ -1,17 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .domain import Domain -from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata +from .domain import Domain class Domains(UniversalBaseModel): custom_domains: typing_extensions.Annotated[ - typing.Optional[typing.List[Domain]], FieldMetadata(alias="customDomains") + typing.Optional[typing.List[Domain]], + FieldMetadata(alias="customDomains"), + pydantic.Field(alias="customDomains"), ] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/ecommerce_settings.py b/src/webflow/types/ecommerce_settings.py index d719e64..b3dd070 100644 --- a/src/webflow/types/ecommerce_settings.py +++ b/src/webflow/types/ecommerce_settings.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions +import datetime as dt import typing -from ..core.serialization import FieldMetadata + import pydantic -import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class EcommerceSettings(UniversalBaseModel): @@ -14,26 +14,21 @@ class EcommerceSettings(UniversalBaseModel): Ecommerce settings for a Webflow Site """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - The identifier of the Site - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - Date that the Site was created on - """ - - default_currency: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="defaultCurrency")] = ( - pydantic.Field(default=None) - ) - """ - The three-letter ISO currency code for the Site - """ + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="The identifier of the Site"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="Date that the Site was created on"), + ] = None + default_currency: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="defaultCurrency"), + pydantic.Field(alias="defaultCurrency", description="The three-letter ISO currency code for the Site"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/error.py b/src/webflow/types/error.py index 0fef21c..1b069e3 100644 --- a/src/webflow/types/error.py +++ b/src/webflow/types/error.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .error_code import ErrorCode + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .error_code import ErrorCode class Error(UniversalBaseModel): @@ -20,14 +20,12 @@ class Error(UniversalBaseModel): Error message """ - external_reference: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="externalReference")] = ( - pydantic.Field(default=None) - ) - """ - Link to more information - """ - - details: typing.Optional[typing.List[typing.Optional[typing.Any]]] = pydantic.Field(default=None) + external_reference: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="externalReference"), + pydantic.Field(alias="externalReference", description="Link to more information"), + ] = None + details: typing.Optional[typing.List[typing.Any]] = pydantic.Field(default=None) """ Array of errors """ diff --git a/src/webflow/types/field.py b/src/webflow/types/field.py index 9543092..7eb4b77 100644 --- a/src/webflow/types/field.py +++ b/src/webflow/types/field.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import typing from .field_type import FieldType from .field_validations import FieldValidations -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Field(UniversalBaseModel): @@ -20,18 +20,16 @@ class Field(UniversalBaseModel): Unique identifier for a Field """ - is_required: typing_extensions.Annotated[bool, FieldMetadata(alias="isRequired")] = pydantic.Field() - """ - define whether a field is required in a collection - """ - - is_editable: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEditable")] = pydantic.Field( - default=None - ) - """ - Define whether the field is editable - """ - + is_required: typing_extensions.Annotated[ + bool, + FieldMetadata(alias="isRequired"), + pydantic.Field(alias="isRequired", description="define whether a field is required in a collection"), + ] + is_editable: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isEditable"), + pydantic.Field(alias="isEditable", description="Define whether the field is editable"), + ] = None type: FieldType = pydantic.Field() """ Choose these appropriate field type for your collection data @@ -42,18 +40,14 @@ class Field(UniversalBaseModel): Slug of Field in Site URL structure. Slugs should be all lowercase with no spaces. Any spaces will be converted to "-." """ - display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() - """ - The name of a field - """ - - help_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="helpText")] = pydantic.Field( - default=None - ) - """ - Additional text to help anyone filling out this field - """ - + display_name: typing_extensions.Annotated[ + str, FieldMetadata(alias="displayName"), pydantic.Field(alias="displayName", description="The name of a field") + ] + help_text: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="helpText"), + pydantic.Field(alias="helpText", description="Additional text to help anyone filling out this field"), + ] = None validations: typing.Optional[FieldValidations] = pydantic.Field(default=None) """ The validations for the field diff --git a/src/webflow/types/field_create.py b/src/webflow/types/field_create.py index 1c9cf61..0d312e5 100644 --- a/src/webflow/types/field_create.py +++ b/src/webflow/types/field_create.py @@ -1,8 +1,9 @@ # This file was auto-generated by Fern from our API Definition. import typing -from .static_field import StaticField + from .option_field import OptionField from .reference_field import ReferenceField +from .static_field import StaticField FieldCreate = typing.Union[StaticField, OptionField, ReferenceField] diff --git a/src/webflow/types/field_validations.py b/src/webflow/types/field_validations.py index ca58a0b..40f076b 100644 --- a/src/webflow/types/field_validations.py +++ b/src/webflow/types/field_validations.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .field_validations_additional_properties import FieldValidationsAdditionalProperties -from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata +from .field_validations_additional_properties import FieldValidationsAdditionalProperties class FieldValidations(UniversalBaseModel): @@ -15,7 +15,9 @@ class FieldValidations(UniversalBaseModel): """ additional_properties: typing_extensions.Annotated[ - typing.Optional[FieldValidationsAdditionalProperties], FieldMetadata(alias="additionalProperties") + typing.Optional[FieldValidationsAdditionalProperties], + FieldMetadata(alias="additionalProperties"), + pydantic.Field(alias="additionalProperties"), ] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/field_validations_additional_properties.py b/src/webflow/types/field_validations_additional_properties.py index ba31807..845d42f 100644 --- a/src/webflow/types/field_validations_additional_properties.py +++ b/src/webflow/types/field_validations_additional_properties.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing + from .field_validations_additional_properties_additional_properties import ( FieldValidationsAdditionalPropertiesAdditionalProperties, ) diff --git a/src/webflow/types/field_validations_additional_properties_additional_properties.py b/src/webflow/types/field_validations_additional_properties_additional_properties.py index aa6c548..0c676dd 100644 --- a/src/webflow/types/field_validations_additional_properties_additional_properties.py +++ b/src/webflow/types/field_validations_additional_properties_additional_properties.py @@ -1,17 +1,17 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class FieldValidationsAdditionalPropertiesAdditionalProperties(UniversalBaseModel): additional_properties: typing_extensions.Annotated[ - typing.Optional[typing.Any], FieldMetadata(alias="additionalProperties") - ] = None + typing.Any, FieldMetadata(alias="additionalProperties"), pydantic.Field(alias="additionalProperties") + ] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/forbidden_error_body.py b/src/webflow/types/forbidden_error_body.py index 5530c7a..24bdcf5 100644 --- a/src/webflow/types/forbidden_error_body.py +++ b/src/webflow/types/forbidden_error_body.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing + from .invalid_scopes import InvalidScopes from .not_enterprise_plan_site import NotEnterprisePlanSite diff --git a/src/webflow/types/form.py b/src/webflow/types/form.py index 0cfef8b..14c7fd9 100644 --- a/src/webflow/types/form.py +++ b/src/webflow/types/form.py @@ -1,14 +1,14 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions +import datetime as dt import typing -from ..core.serialization import FieldMetadata + import pydantic -import datetime as dt +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .form_field import FormField from .form_response_settings import FormResponseSettings -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Form(UniversalBaseModel): @@ -16,85 +16,66 @@ class Form(UniversalBaseModel): A Webflow form """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) - """ - The Form name displayed on the site - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - Date that the Form was created on - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - Date that the Form was last updated on - """ - + display_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="displayName"), + pydantic.Field(alias="displayName", description="The Form name displayed on the site"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="Date that the Form was created on"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="Date that the Form was last updated on"), + ] = None fields: typing.Optional[FormField] = pydantic.Field(default=None) """ A collection of form field objects """ response_settings: typing_extensions.Annotated[ - typing.Optional[FormResponseSettings], FieldMetadata(alias="responseSettings") - ] = pydantic.Field(default=None) - """ - Settings for form responses - """ - + typing.Optional[FormResponseSettings], + FieldMetadata(alias="responseSettings"), + pydantic.Field(alias="responseSettings", description="Settings for form responses"), + ] = None id: typing.Optional[str] = pydantic.Field(default=None) """ The unique ID for the Form """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - The unique ID of the Site the Form belongs to - """ - - site_domain_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteDomainId")] = ( - pydantic.Field(default=None) - ) - """ - The unique ID corresponding to the site's Domain name - """ - - page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = pydantic.Field( - default=None - ) - """ - The unique ID for the Page on which the Form is placed - """ - - page_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageName")] = pydantic.Field( - default=None - ) - """ - The user-visible name of the Page where the Form is placed - """ - - form_element_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="formElementId")] = ( - pydantic.Field(default=None) - ) - """ - The unique ID of the Form element - """ - - workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( - pydantic.Field(default=None) - ) - """ - The unique ID of the Workspace the Site belongs to - """ + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="The unique ID of the Site the Form belongs to"), + ] = None + site_domain_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteDomainId"), + pydantic.Field(alias="siteDomainId", description="The unique ID corresponding to the site's Domain name"), + ] = None + page_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="pageId"), + pydantic.Field(alias="pageId", description="The unique ID for the Page on which the Form is placed"), + ] = None + page_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="pageName"), + pydantic.Field(alias="pageName", description="The user-visible name of the Page where the Form is placed"), + ] = None + form_element_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="formElementId"), + pydantic.Field(alias="formElementId", description="The unique ID of the Form element"), + ] = None + workspace_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="workspaceId"), + pydantic.Field(alias="workspaceId", description="The unique ID of the Workspace the Site belongs to"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/form_field.py b/src/webflow/types/form_field.py index d62b01e..f76bdcb 100644 --- a/src/webflow/types/form_field.py +++ b/src/webflow/types/form_field.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing + from .form_field_value import FormFieldValue FormField = typing.Dict[str, FormFieldValue] diff --git a/src/webflow/types/form_field_value.py b/src/webflow/types/form_field_value.py index 957624d..51e8102 100644 --- a/src/webflow/types/form_field_value.py +++ b/src/webflow/types/form_field_value.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .form_field_value_type import FormFieldValueType -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class FormFieldValue(UniversalBaseModel): @@ -14,13 +14,11 @@ class FormFieldValue(UniversalBaseModel): An object containing field info for a specific fieldID. """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) - """ - The field name displayed on the site - """ - + display_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="displayName"), + pydantic.Field(alias="displayName", description="The field name displayed on the site"), + ] = None type: typing.Optional[FormFieldValueType] = pydantic.Field(default=None) """ The field type @@ -31,12 +29,11 @@ class FormFieldValue(UniversalBaseModel): The placeholder text for the field """ - user_visible: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="userVisible")] = ( - pydantic.Field(default=None) - ) - """ - Whether the field is visible to the user - """ + user_visible: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="userVisible"), + pydantic.Field(alias="userVisible", description="Whether the field is visible to the user"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/form_list.py b/src/webflow/types/form_list.py index 17590c6..c8fe917 100644 --- a/src/webflow/types/form_list.py +++ b/src/webflow/types/form_list.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .form import Form from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class FormList(UniversalBaseModel): diff --git a/src/webflow/types/form_response_settings.py b/src/webflow/types/form_response_settings.py index c51d6b6..0acae41 100644 --- a/src/webflow/types/form_response_settings.py +++ b/src/webflow/types/form_response_settings.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class FormResponseSettings(UniversalBaseModel): @@ -13,33 +13,30 @@ class FormResponseSettings(UniversalBaseModel): Settings for form responses """ - redirect_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="redirectUrl")] = ( - pydantic.Field(default=None) - ) - """ - The url or path to redirect the user to after form submission - """ - - redirect_method: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="redirectMethod")] = ( - pydantic.Field(default=None) - ) - """ - The HTTP request method to use for the redirectUrl (eg. POST or GET) - """ - - redirect_action: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="redirectAction")] = ( - pydantic.Field(default=None) - ) - """ - The action to take after form submission - """ - + redirect_url: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="redirectUrl"), + pydantic.Field( + alias="redirectUrl", description="The url or path to redirect the user to after form submission" + ), + ] = None + redirect_method: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="redirectMethod"), + pydantic.Field( + alias="redirectMethod", description="The HTTP request method to use for the redirectUrl (eg. POST or GET)" + ), + ] = None + redirect_action: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="redirectAction"), + pydantic.Field(alias="redirectAction", description="The action to take after form submission"), + ] = None send_email_confirmation: typing_extensions.Annotated[ - typing.Optional[bool], FieldMetadata(alias="sendEmailConfirmation") - ] = pydantic.Field(default=None) - """ - Whether to send an email confirmation to the user - """ + typing.Optional[bool], + FieldMetadata(alias="sendEmailConfirmation"), + pydantic.Field(alias="sendEmailConfirmation", description="Whether to send an email confirmation to the user"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/form_submission.py b/src/webflow/types/form_submission.py index cd18202..adf12b7 100644 --- a/src/webflow/types/form_submission.py +++ b/src/webflow/types/form_submission.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class FormSubmission(UniversalBaseModel): @@ -15,40 +15,31 @@ class FormSubmission(UniversalBaseModel): The unique ID of the Form submission """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) - """ - The Form name displayed on the site - """ - - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - The unique ID of the Site the Form belongs to - """ - - workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( - pydantic.Field(default=None) - ) - """ - The unique ID of the Workspace the Site belongs to - """ - - date_submitted: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="dateSubmitted")] = ( - pydantic.Field(default=None) - ) - """ - Date that the Form was submitted on - """ - + display_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="displayName"), + pydantic.Field(alias="displayName", description="The Form name displayed on the site"), + ] = None + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="The unique ID of the Site the Form belongs to"), + ] = None + workspace_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="workspaceId"), + pydantic.Field(alias="workspaceId", description="The unique ID of the Workspace the Site belongs to"), + ] = None + date_submitted: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="dateSubmitted"), + pydantic.Field(alias="dateSubmitted", description="Date that the Form was submitted on"), + ] = None form_response: typing_extensions.Annotated[ - typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]], FieldMetadata(alias="formResponse") - ] = pydantic.Field(default=None) - """ - The data submitted in the Form - """ + typing.Optional[typing.Dict[str, typing.Any]], + FieldMetadata(alias="formResponse"), + pydantic.Field(alias="formResponse", description="The data submitted in the Form"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/form_submission_list.py b/src/webflow/types/form_submission_list.py index c9099a1..356c370 100644 --- a/src/webflow/types/form_submission_list.py +++ b/src/webflow/types/form_submission_list.py @@ -1,18 +1,20 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .form_submission import FormSubmission + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata +from .form_submission import FormSubmission from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class FormSubmissionList(UniversalBaseModel): form_submissions: typing_extensions.Annotated[ - typing.Optional[typing.List[FormSubmission]], FieldMetadata(alias="formSubmissions") + typing.Optional[typing.List[FormSubmission]], + FieldMetadata(alias="formSubmissions"), + pydantic.Field(alias="formSubmissions"), ] = None pagination: typing.Optional[Pagination] = None diff --git a/src/webflow/types/form_submission_trigger.py b/src/webflow/types/form_submission_trigger.py index 82f1eaf..f7c31f7 100644 --- a/src/webflow/types/form_submission_trigger.py +++ b/src/webflow/types/form_submission_trigger.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .form_submission_trigger_payload import FormSubmissionTriggerPayload -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class FormSubmissionTrigger(UniversalBaseModel): @@ -14,13 +14,11 @@ class FormSubmissionTrigger(UniversalBaseModel): The Webhook payload for when a form is submitted """ - trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( - pydantic.Field(default=None) - ) - """ - The type of event that triggered the request - """ - + trigger_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = None payload: typing.Optional[FormSubmissionTriggerPayload] = pydantic.Field(default=None) """ The payload of data sent from Webflow diff --git a/src/webflow/types/form_submission_trigger_payload.py b/src/webflow/types/form_submission_trigger_payload.py index f192a9f..d715049 100644 --- a/src/webflow/types/form_submission_trigger_payload.py +++ b/src/webflow/types/form_submission_trigger_payload.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .form_submission_trigger_payload_schema_item import FormSubmissionTriggerPayloadSchemaItem -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class FormSubmissionTriggerPayload(UniversalBaseModel): @@ -19,50 +19,41 @@ class FormSubmissionTriggerPayload(UniversalBaseModel): The name of the form """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - The ID of the site that the form was submitted from - """ - - data: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="The ID of the site that the form was submitted from"), + ] = None + data: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None) """ The data submitted in the form """ schema_: typing_extensions.Annotated[ - typing.Optional[typing.List[FormSubmissionTriggerPayloadSchemaItem]], FieldMetadata(alias="schema") - ] = pydantic.Field(default=None) - """ - A list of fields from the submitted form - """ - - submitted_at: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="submittedAt")] = ( - pydantic.Field(default=None) - ) - """ - The timestamp the form was submitted - """ - + typing.Optional[typing.List[FormSubmissionTriggerPayloadSchemaItem]], + FieldMetadata(alias="schema"), + pydantic.Field(alias="schema", description="A list of fields from the submitted form"), + ] = None + submitted_at: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="submittedAt"), + pydantic.Field(alias="submittedAt", description="The timestamp the form was submitted"), + ] = None id: typing.Optional[str] = pydantic.Field(default=None) """ the ID of the event """ - form_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="formId")] = pydantic.Field( - default=None - ) - """ - The ID of the form submission - """ - - form_element_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="formElementId")] = ( - pydantic.Field(default=None) - ) - """ - The uniqueID of the Form element - """ + form_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="formId"), + pydantic.Field(alias="formId", description="The ID of the form submission"), + ] = None + form_element_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="formElementId"), + pydantic.Field(alias="formElementId", description="The uniqueID of the Form element"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/form_submission_trigger_payload_schema_item.py b/src/webflow/types/form_submission_trigger_payload_schema_item.py index 014322f..7550cfc 100644 --- a/src/webflow/types/form_submission_trigger_payload_schema_item.py +++ b/src/webflow/types/form_submission_trigger_payload_schema_item.py @@ -1,35 +1,30 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .form_submission_trigger_payload_schema_item_field_type import FormSubmissionTriggerPayloadSchemaItemFieldType -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class FormSubmissionTriggerPayloadSchemaItem(UniversalBaseModel): - field_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="fieldName")] = pydantic.Field( - default=None - ) - """ - Form field name - """ - + field_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="fieldName"), + pydantic.Field(alias="fieldName", description="Form field name"), + ] = None field_type: typing_extensions.Annotated[ - typing.Optional[FormSubmissionTriggerPayloadSchemaItemFieldType], FieldMetadata(alias="fieldType") - ] = pydantic.Field(default=None) - """ - Form field type - """ - - field_element_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="fieldElementId")] = ( - pydantic.Field(default=None) - ) - """ - Element ID of the Form Field - """ + typing.Optional[FormSubmissionTriggerPayloadSchemaItemFieldType], + FieldMetadata(alias="fieldType"), + pydantic.Field(alias="fieldType", description="Form field type"), + ] = None + field_element_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="fieldElementId"), + pydantic.Field(alias="fieldElementId", description="Element ID of the Form Field"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/image_node.py b/src/webflow/types/image_node.py index c4e7eac..56cf7cc 100644 --- a/src/webflow/types/image_node.py +++ b/src/webflow/types/image_node.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .image_node_image import ImageNodeImage -import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class ImageNode(UniversalBaseModel): diff --git a/src/webflow/types/image_node_image.py b/src/webflow/types/image_node_image.py index f8d9379..1415afb 100644 --- a/src/webflow/types/image_node_image.py +++ b/src/webflow/types/image_node_image.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class ImageNodeImage(UniversalBaseModel): @@ -14,7 +14,9 @@ class ImageNodeImage(UniversalBaseModel): """ alt: typing.Optional[str] = None - asset_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="assetId")] = None + asset_id: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="assetId"), pydantic.Field(alias="assetId") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/invalid_domain.py b/src/webflow/types/invalid_domain.py index 60e64b7..304487f 100644 --- a/src/webflow/types/invalid_domain.py +++ b/src/webflow/types/invalid_domain.py @@ -2,4 +2,4 @@ import typing -InvalidDomain = typing.Optional[typing.Any] +InvalidDomain = typing.Any diff --git a/src/webflow/types/invalid_scopes.py b/src/webflow/types/invalid_scopes.py index 90edaa0..babfdd3 100644 --- a/src/webflow/types/invalid_scopes.py +++ b/src/webflow/types/invalid_scopes.py @@ -2,4 +2,4 @@ import typing -InvalidScopes = typing.Optional[typing.Any] +InvalidScopes = typing.Any diff --git a/src/webflow/types/inventory_item.py b/src/webflow/types/inventory_item.py index 3eda2d3..5db3ff3 100644 --- a/src/webflow/types/inventory_item.py +++ b/src/webflow/types/inventory_item.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions -from .inventory_item_inventory_type import InventoryItemInventoryType +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .inventory_item_inventory_type import InventoryItemInventoryType class InventoryItem(UniversalBaseModel): @@ -25,11 +25,10 @@ class InventoryItem(UniversalBaseModel): """ inventory_type: typing_extensions.Annotated[ - typing.Optional[InventoryItemInventoryType], FieldMetadata(alias="inventoryType") - ] = pydantic.Field(default=None) - """ - infinite or finite - """ + typing.Optional[InventoryItemInventoryType], + FieldMetadata(alias="inventoryType"), + pydantic.Field(alias="inventoryType", description="infinite or finite"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/items_list_items_live_request_last_published.py b/src/webflow/types/items_list_items_live_request_last_published.py index 31aab15..ec7c86a 100644 --- a/src/webflow/types/items_list_items_live_request_last_published.py +++ b/src/webflow/types/items_list_items_live_request_last_published.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing import datetime as dt +import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class ItemsListItemsLiveRequestLastPublished(UniversalBaseModel): diff --git a/src/webflow/types/items_list_items_request_last_published.py b/src/webflow/types/items_list_items_request_last_published.py index bf4505d..05dc5c2 100644 --- a/src/webflow/types/items_list_items_request_last_published.py +++ b/src/webflow/types/items_list_items_request_last_published.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing import datetime as dt +import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class ItemsListItemsRequestLastPublished(UniversalBaseModel): diff --git a/src/webflow/types/list_custom_code_blocks.py b/src/webflow/types/list_custom_code_blocks.py index 417c456..9f5d58e 100644 --- a/src/webflow/types/list_custom_code_blocks.py +++ b/src/webflow/types/list_custom_code_blocks.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .custom_code_block import CustomCodeBlock from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class ListCustomCodeBlocks(UniversalBaseModel): diff --git a/src/webflow/types/locale.py b/src/webflow/types/locale.py index ba88d45..19df91b 100644 --- a/src/webflow/types/locale.py +++ b/src/webflow/types/locale.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Locale(UniversalBaseModel): @@ -14,32 +14,28 @@ class Locale(UniversalBaseModel): The unique identifier for the locale. """ - cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( - pydantic.Field(default=None) - ) - """ - A CMS-specific identifier for the locale. - """ - + cms_locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="cmsLocaleId"), + pydantic.Field(alias="cmsLocaleId", description="A CMS-specific identifier for the locale."), + ] = None enabled: typing.Optional[bool] = pydantic.Field(default=None) """ Indicates if the locale is enabled. """ - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) - """ - The display name of the locale, typically in English. - """ - - display_image_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayImageId")] = ( - pydantic.Field(default=None) - ) - """ - An optional ID for an image associated with the locale, nullable. - """ - + display_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="displayName"), + pydantic.Field(alias="displayName", description="The display name of the locale, typically in English."), + ] = None + display_image_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="displayImageId"), + pydantic.Field( + alias="displayImageId", description="An optional ID for an image associated with the locale, nullable." + ), + ] = None redirect: typing.Optional[bool] = pydantic.Field(default=None) """ Determines if requests should redirect to the locale's subdirectory. diff --git a/src/webflow/types/locales.py b/src/webflow/types/locales.py index 7dad886..3d253a1 100644 --- a/src/webflow/types/locales.py +++ b/src/webflow/types/locales.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .locale import Locale + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .locale import Locale class Locales(UniversalBaseModel): diff --git a/src/webflow/types/metadata.py b/src/webflow/types/metadata.py index 1c9caa7..576efc7 100644 --- a/src/webflow/types/metadata.py +++ b/src/webflow/types/metadata.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .metadata_options_item import MetadataOptionsItem + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .metadata_options_item import MetadataOptionsItem class Metadata(UniversalBaseModel): diff --git a/src/webflow/types/metadata_options_item.py b/src/webflow/types/metadata_options_item.py index 91eb360..5618523 100644 --- a/src/webflow/types/metadata_options_item.py +++ b/src/webflow/types/metadata_options_item.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class MetadataOptionsItem(UniversalBaseModel): diff --git a/src/webflow/types/new_order.py b/src/webflow/types/new_order.py index c156c65..89296a7 100644 --- a/src/webflow/types/new_order.py +++ b/src/webflow/types/new_order.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .order import Order -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class NewOrder(UniversalBaseModel): @@ -14,13 +14,11 @@ class NewOrder(UniversalBaseModel): The Webhook payload for when a new order is created """ - trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( - pydantic.Field(default=None) - ) - """ - The type of event that triggered the request - """ - + trigger_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = None payload: typing.Optional[Order] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/no_domains.py b/src/webflow/types/no_domains.py index 714031f..c9162ec 100644 --- a/src/webflow/types/no_domains.py +++ b/src/webflow/types/no_domains.py @@ -2,4 +2,4 @@ import typing -NoDomains = typing.Optional[typing.Any] +NoDomains = typing.Any diff --git a/src/webflow/types/node.py b/src/webflow/types/node.py index 6ec64b9..f413d08 100644 --- a/src/webflow/types/node.py +++ b/src/webflow/types/node.py @@ -1,16 +1,17 @@ # This file was auto-generated by Fern from our API Definition. from __future__ import annotations -from ..core.pydantic_utilities import UniversalBaseModel + import typing -from .text_node_text import TextNodeText -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic -from .image_node_image import ImageNodeImage import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .component_property import ComponentProperty +from .image_node_image import ImageNodeImage from .select_node_choices_item import SelectNodeChoicesItem +from .text_node_text import TextNodeText class Node_Text(UniversalBaseModel): @@ -60,9 +61,13 @@ class Node_ComponentInstance(UniversalBaseModel): type: typing.Literal["component-instance"] = "component-instance" id: str - component_id: typing_extensions.Annotated[str, FieldMetadata(alias="componentId")] + component_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="componentId"), pydantic.Field(alias="componentId") + ] property_overrides: typing_extensions.Annotated[ - typing.List[ComponentProperty], FieldMetadata(alias="propertyOverrides") + typing.List[ComponentProperty], + FieldMetadata(alias="propertyOverrides"), + pydantic.Field(alias="propertyOverrides"), ] if IS_PYDANTIC_V2: @@ -123,7 +128,9 @@ class Node_SubmitButton(UniversalBaseModel): type: typing.Literal["submit-button"] = "submit-button" id: str value: str - waiting_text: typing_extensions.Annotated[str, FieldMetadata(alias="waitingText")] + waiting_text: typing_extensions.Annotated[ + str, FieldMetadata(alias="waitingText"), pydantic.Field(alias="waitingText") + ] attributes: typing.Optional[typing.Dict[str, str]] = None if IS_PYDANTIC_V2: @@ -156,6 +163,9 @@ class Config: extra = pydantic.Extra.allow -Node = typing.Union[ - Node_Text, Node_Image, Node_ComponentInstance, Node_TextInput, Node_Select, Node_SubmitButton, Node_SearchButton +Node = typing_extensions.Annotated[ + typing.Union[ + Node_Text, Node_Image, Node_ComponentInstance, Node_TextInput, Node_Select, Node_SubmitButton, Node_SearchButton + ], + pydantic.Field(discriminator="type"), ] diff --git a/src/webflow/types/not_enterprise_plan_site.py b/src/webflow/types/not_enterprise_plan_site.py index 87003ce..1001cf8 100644 --- a/src/webflow/types/not_enterprise_plan_site.py +++ b/src/webflow/types/not_enterprise_plan_site.py @@ -2,4 +2,4 @@ import typing -NotEnterprisePlanSite = typing.Optional[typing.Any] +NotEnterprisePlanSite = typing.Any diff --git a/src/webflow/types/not_enterprise_plan_workspace.py b/src/webflow/types/not_enterprise_plan_workspace.py index e093b54..c945214 100644 --- a/src/webflow/types/not_enterprise_plan_workspace.py +++ b/src/webflow/types/not_enterprise_plan_workspace.py @@ -2,4 +2,4 @@ import typing -NotEnterprisePlanWorkspace = typing.Optional[typing.Any] +NotEnterprisePlanWorkspace = typing.Any diff --git a/src/webflow/types/option_field.py b/src/webflow/types/option_field.py index 7f7c6d5..ea1a98a 100644 --- a/src/webflow/types/option_field.py +++ b/src/webflow/types/option_field.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .metadata import Metadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class OptionField(UniversalBaseModel): @@ -15,37 +15,29 @@ class OptionField(UniversalBaseModel): Unique identifier for a Field """ - is_editable: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEditable")] = pydantic.Field( - default=None - ) - """ - Define whether the field is editable - """ - - is_required: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isRequired")] = pydantic.Field( - default=None - ) - """ - define whether a field is required in a collection - """ - + is_editable: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isEditable"), + pydantic.Field(alias="isEditable", description="Define whether the field is editable"), + ] = None + is_required: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isRequired"), + pydantic.Field(alias="isRequired", description="define whether a field is required in a collection"), + ] = None type: typing.Literal["Option"] = pydantic.Field(default="Option") """ The [Option field type](/data/reference/field-types-item-values#option) """ - display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() - """ - The name of a field - """ - - help_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="helpText")] = pydantic.Field( - default=None - ) - """ - Additional text to help anyone filling out this field - """ - + display_name: typing_extensions.Annotated[ + str, FieldMetadata(alias="displayName"), pydantic.Field(alias="displayName", description="The name of a field") + ] + help_text: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="helpText"), + pydantic.Field(alias="helpText", description="Additional text to help anyone filling out this field"), + ] = None metadata: Metadata if IS_PYDANTIC_V2: diff --git a/src/webflow/types/order.py b/src/webflow/types/order.py index 2b2844c..56f1196 100644 --- a/src/webflow/types/order.py +++ b/src/webflow/types/order.py @@ -1,38 +1,37 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions +import datetime as dt import typing -from ..core.serialization import FieldMetadata + import pydantic -from .order_status import OrderStatus -import datetime as dt -from .order_dispute_last_status import OrderDisputeLastStatus -from .order_price import OrderPrice +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .order_address import OrderAddress -from .order_shipping_address import OrderShippingAddress from .order_billing_address import OrderBillingAddress from .order_customer_info import OrderCustomerInfo -from .order_purchased_item import OrderPurchasedItem -from .stripe_details import StripeDetails -from .stripe_card import StripeCard -from .paypal_details import PaypalDetails +from .order_dispute_last_status import OrderDisputeLastStatus +from .order_download_files_item import OrderDownloadFilesItem from .order_metadata import OrderMetadata +from .order_price import OrderPrice +from .order_purchased_item import OrderPurchasedItem +from .order_shipping_address import OrderShippingAddress +from .order_status import OrderStatus from .order_totals import OrderTotals -from .order_download_files_item import OrderDownloadFilesItem -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .paypal_details import PaypalDetails +from .stripe_card import StripeCard +from .stripe_details import StripeDetails class Order(UniversalBaseModel): - order_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="orderId")] = pydantic.Field( - default=None - ) - """ - The order ID. Will usually be 6 hex characters, but can also be 9 - hex characters if the site has a very large number of Orders. - Randomly assigned. - """ - + order_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="orderId"), + pydantic.Field( + alias="orderId", + description="The order ID. Will usually be 6 hex characters, but can also be 9\nhex characters if the site has a very large number of Orders.\nRandomly assigned.", + ), + ] = None status: typing.Optional[OrderStatus] = pydantic.Field(default=None) """ The status of the Order @@ -43,189 +42,181 @@ class Order(UniversalBaseModel): A comment string for this Order, which is editable by API user (not used by Webflow). """ - order_comment: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="orderComment")] = ( - pydantic.Field(default=None) - ) - """ - A comment that the customer left when making their Order - """ - - accepted_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="acceptedOn")] = ( - pydantic.Field(default=None) - ) - """ - The ISO8601 timestamp that an Order was placed. - """ - - fulfilled_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="fulfilledOn")] = ( - pydantic.Field(default=None) - ) - """ - When an Order is marked as 'fulfilled', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. - """ - - refunded_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="refundedOn")] = ( - pydantic.Field(default=None) - ) - """ - When an Order is marked as 'refunded', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. - """ - - disputed_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="disputedOn")] = ( - pydantic.Field(default=None) - ) - """ - When an Order is marked as 'disputed', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null. - """ - + order_comment: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="orderComment"), + pydantic.Field(alias="orderComment", description="A comment that the customer left when making their Order"), + ] = None + accepted_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="acceptedOn"), + pydantic.Field(alias="acceptedOn", description="The ISO8601 timestamp that an Order was placed."), + ] = None + fulfilled_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="fulfilledOn"), + pydantic.Field( + alias="fulfilledOn", + description="When an Order is marked as 'fulfilled', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null.", + ), + ] = None + refunded_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="refundedOn"), + pydantic.Field( + alias="refundedOn", + description="When an Order is marked as 'refunded', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null.", + ), + ] = None + disputed_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="disputedOn"), + pydantic.Field( + alias="disputedOn", + description="When an Order is marked as 'disputed', this field represents the timestamp of the fulfillment in ISO8601 format. Otherwise, it is null.", + ), + ] = None dispute_updated_on: typing_extensions.Annotated[ - typing.Optional[dt.datetime], FieldMetadata(alias="disputeUpdatedOn") - ] = pydantic.Field(default=None) - """ - If an Order has been disputed by the customer, this key will be set to the ISO8601 timestamp of the last update received. If the Order is not disputed, the key will be null. - """ - + typing.Optional[dt.datetime], + FieldMetadata(alias="disputeUpdatedOn"), + pydantic.Field( + alias="disputeUpdatedOn", + description="If an Order has been disputed by the customer, this key will be set to the ISO8601 timestamp of the last update received. If the Order is not disputed, the key will be null.", + ), + ] = None dispute_last_status: typing_extensions.Annotated[ - typing.Optional[OrderDisputeLastStatus], FieldMetadata(alias="disputeLastStatus") - ] = pydantic.Field(default=None) - """ - If an order was disputed by the customer, then this key will be set with the [dispute's status](https://stripe.com/docs/api#dispute_object-status). - """ - - customer_paid: typing_extensions.Annotated[typing.Optional[OrderPrice], FieldMetadata(alias="customerPaid")] = ( - pydantic.Field(default=None) - ) - """ - The total paid by the customer - """ - - net_amount: typing_extensions.Annotated[typing.Optional[OrderPrice], FieldMetadata(alias="netAmount")] = ( - pydantic.Field(default=None) - ) - """ - The net amount after application fees - """ - - application_fee: typing_extensions.Annotated[typing.Optional[OrderPrice], FieldMetadata(alias="applicationFee")] = ( - pydantic.Field(default=None) - ) - """ - The application fee assessed by the platform - """ - + typing.Optional[OrderDisputeLastStatus], + FieldMetadata(alias="disputeLastStatus"), + pydantic.Field( + alias="disputeLastStatus", + description="If an order was disputed by the customer, then this key will be set with the [dispute's status](https://stripe.com/docs/api#dispute_object-status).", + ), + ] = None + customer_paid: typing_extensions.Annotated[ + typing.Optional[OrderPrice], + FieldMetadata(alias="customerPaid"), + pydantic.Field(alias="customerPaid", description="The total paid by the customer"), + ] = None + net_amount: typing_extensions.Annotated[ + typing.Optional[OrderPrice], + FieldMetadata(alias="netAmount"), + pydantic.Field(alias="netAmount", description="The net amount after application fees"), + ] = None + application_fee: typing_extensions.Annotated[ + typing.Optional[OrderPrice], + FieldMetadata(alias="applicationFee"), + pydantic.Field(alias="applicationFee", description="The application fee assessed by the platform"), + ] = None all_addresses: typing_extensions.Annotated[ - typing.Optional[typing.List[OrderAddress]], FieldMetadata(alias="allAddresses") - ] = pydantic.Field(default=None) - """ - All addresses provided by the customer during the ordering flow. - """ - + typing.Optional[typing.List[OrderAddress]], + FieldMetadata(alias="allAddresses"), + pydantic.Field( + alias="allAddresses", description="All addresses provided by the customer during the ordering flow." + ), + ] = None shipping_address: typing_extensions.Annotated[ - typing.Optional[OrderShippingAddress], FieldMetadata(alias="shippingAddress") - ] = pydantic.Field(default=None) - """ - The shipping address - """ - + typing.Optional[OrderShippingAddress], + FieldMetadata(alias="shippingAddress"), + pydantic.Field(alias="shippingAddress", description="The shipping address"), + ] = None billing_address: typing_extensions.Annotated[ - typing.Optional[OrderBillingAddress], FieldMetadata(alias="billingAddress") - ] = pydantic.Field(default=None) - """ - The billing address - """ - - shipping_provider: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="shippingProvider")] = ( - pydantic.Field(default=None) - ) - """ - A string editable by the API user to note the shipping provider used (not used by Webflow). - """ - - shipping_tracking: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="shippingTracking")] = ( - pydantic.Field(default=None) - ) - """ - A string editable by the API user to note the shipping tracking number for the order (not used by Webflow). - """ - + typing.Optional[OrderBillingAddress], + FieldMetadata(alias="billingAddress"), + pydantic.Field(alias="billingAddress", description="The billing address"), + ] = None + shipping_provider: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="shippingProvider"), + pydantic.Field( + alias="shippingProvider", + description="A string editable by the API user to note the shipping provider used (not used by Webflow).", + ), + ] = None + shipping_tracking: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="shippingTracking"), + pydantic.Field( + alias="shippingTracking", + description="A string editable by the API user to note the shipping tracking number for the order (not used by Webflow).", + ), + ] = None shipping_tracking_url: typing_extensions.Annotated[ - typing.Optional[str], FieldMetadata(alias="shippingTrackingURL") + typing.Optional[str], FieldMetadata(alias="shippingTrackingURL"), pydantic.Field(alias="shippingTrackingURL") ] = None customer_info: typing_extensions.Annotated[ - typing.Optional[OrderCustomerInfo], FieldMetadata(alias="customerInfo") - ] = pydantic.Field(default=None) - """ - An object with the keys `fullName` and `email`. - """ - + typing.Optional[OrderCustomerInfo], + FieldMetadata(alias="customerInfo"), + pydantic.Field(alias="customerInfo", description="An object with the keys `fullName` and `email`."), + ] = None purchased_items: typing_extensions.Annotated[ - typing.Optional[typing.List[OrderPurchasedItem]], FieldMetadata(alias="purchasedItems") - ] = pydantic.Field(default=None) - """ - An array of all things that the Customer purchased. - """ - + typing.Optional[typing.List[OrderPurchasedItem]], + FieldMetadata(alias="purchasedItems"), + pydantic.Field(alias="purchasedItems", description="An array of all things that the Customer purchased."), + ] = None purchased_items_count: typing_extensions.Annotated[ - typing.Optional[float], FieldMetadata(alias="purchasedItemsCount") - ] = pydantic.Field(default=None) - """ - The sum of all 'count' fields in 'purchasedItems'. - """ - + typing.Optional[float], + FieldMetadata(alias="purchasedItemsCount"), + pydantic.Field(alias="purchasedItemsCount", description="The sum of all 'count' fields in 'purchasedItems'."), + ] = None stripe_details: typing_extensions.Annotated[ - typing.Optional[StripeDetails], FieldMetadata(alias="stripeDetails") + typing.Optional[StripeDetails], FieldMetadata(alias="stripeDetails"), pydantic.Field(alias="stripeDetails") + ] = None + stripe_card: typing_extensions.Annotated[ + typing.Optional[StripeCard], FieldMetadata(alias="stripeCard"), pydantic.Field(alias="stripeCard") ] = None - stripe_card: typing_extensions.Annotated[typing.Optional[StripeCard], FieldMetadata(alias="stripeCard")] = None paypal_details: typing_extensions.Annotated[ - typing.Optional[PaypalDetails], FieldMetadata(alias="paypalDetails") + typing.Optional[PaypalDetails], FieldMetadata(alias="paypalDetails"), pydantic.Field(alias="paypalDetails") ] = None custom_data: typing_extensions.Annotated[ - typing.Optional[typing.List[typing.Dict[str, typing.Optional[typing.Any]]]], FieldMetadata(alias="customData") - ] = pydantic.Field(default=None) - """ - An array of additional inputs for custom order data gathering. Each object in the array represents an input with a name, and a textInput, textArea, or checkbox value. - """ - + typing.Optional[typing.List[typing.Dict[str, typing.Any]]], + FieldMetadata(alias="customData"), + pydantic.Field( + alias="customData", + description="An array of additional inputs for custom order data gathering. Each object in the array represents an input with a name, and a textInput, textArea, or checkbox value.", + ), + ] = None metadata: typing.Optional[OrderMetadata] = None is_customer_deleted: typing_extensions.Annotated[ - typing.Optional[bool], FieldMetadata(alias="isCustomerDeleted") - ] = pydantic.Field(default=None) - """ - A boolean indicating whether the customer has been deleted from the site. - """ - + typing.Optional[bool], + FieldMetadata(alias="isCustomerDeleted"), + pydantic.Field( + alias="isCustomerDeleted", + description="A boolean indicating whether the customer has been deleted from the site.", + ), + ] = None is_shipping_required: typing_extensions.Annotated[ - typing.Optional[bool], FieldMetadata(alias="isShippingRequired") - ] = pydantic.Field(default=None) - """ - A boolean indicating whether the order contains one or more purchased items that require shipping. - """ - - has_downloads: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="hasDownloads")] = ( - pydantic.Field(default=None) - ) - """ - A boolean indicating whether the order contains one or more purchased items that are downloadable. - """ - - payment_processor: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="paymentProcessor")] = ( - pydantic.Field(default=None) - ) - """ - A string indicating the payment processor used for this order. - """ - + typing.Optional[bool], + FieldMetadata(alias="isShippingRequired"), + pydantic.Field( + alias="isShippingRequired", + description="A boolean indicating whether the order contains one or more purchased items that require shipping.", + ), + ] = None + has_downloads: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="hasDownloads"), + pydantic.Field( + alias="hasDownloads", + description="A boolean indicating whether the order contains one or more purchased items that are downloadable.", + ), + ] = None + payment_processor: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="paymentProcessor"), + pydantic.Field( + alias="paymentProcessor", description="A string indicating the payment processor used for this order." + ), + ] = None totals: typing.Optional[OrderTotals] = pydantic.Field(default=None) """ An object describing various pricing totals """ download_files: typing_extensions.Annotated[ - typing.Optional[typing.List[OrderDownloadFilesItem]], FieldMetadata(alias="downloadFiles") - ] = pydantic.Field(default=None) - """ - An array of downloadable file objects. - """ + typing.Optional[typing.List[OrderDownloadFilesItem]], + FieldMetadata(alias="downloadFiles"), + pydantic.Field(alias="downloadFiles", description="An array of downloadable file objects."), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/order_address.py b/src/webflow/types/order_address.py index f225bc3..ad31ad4 100644 --- a/src/webflow/types/order_address.py +++ b/src/webflow/types/order_address.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .order_address_type import OrderAddressType + import pydantic import typing_extensions -from .order_address_japan_type import OrderAddressJapanType +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .order_address_japan_type import OrderAddressJapanType +from .order_address_type import OrderAddressType class OrderAddress(UniversalBaseModel): @@ -21,31 +21,28 @@ class OrderAddress(UniversalBaseModel): """ japan_type: typing_extensions.Annotated[ - typing.Optional[OrderAddressJapanType], FieldMetadata(alias="japanType") - ] = pydantic.Field(default=None) - """ - Represents a Japan-only address format. This field will only appear on orders placed from Japan. - """ - + typing.Optional[OrderAddressJapanType], + FieldMetadata(alias="japanType"), + pydantic.Field( + alias="japanType", + description="Represents a Japan-only address format. This field will only appear on orders placed from Japan.", + ), + ] = None addressee: typing.Optional[str] = pydantic.Field(default=None) """ Display name on the address """ - line_1: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line1")] = pydantic.Field( - default=None - ) - """ - The first line of the address - """ - - line_2: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line2")] = pydantic.Field( - default=None - ) - """ - The second line of the address - """ - + line_1: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="line1"), + pydantic.Field(alias="line1", description="The first line of the address"), + ] = None + line_2: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="line2"), + pydantic.Field(alias="line2", description="The second line of the address"), + ] = None city: typing.Optional[str] = pydantic.Field(default=None) """ The city of the address. @@ -61,12 +58,11 @@ class OrderAddress(UniversalBaseModel): The country of the address """ - postal_code: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="postalCode")] = pydantic.Field( - default=None - ) - """ - The postal code of the address - """ + postal_code: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="postalCode"), + pydantic.Field(alias="postalCode", description="The postal code of the address"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/order_billing_address.py b/src/webflow/types/order_billing_address.py index 75e87c6..484d367 100644 --- a/src/webflow/types/order_billing_address.py +++ b/src/webflow/types/order_billing_address.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .order_billing_address_type import OrderBillingAddressType + import pydantic import typing_extensions -from .order_billing_address_japan_type import OrderBillingAddressJapanType +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .order_billing_address_japan_type import OrderBillingAddressJapanType +from .order_billing_address_type import OrderBillingAddressType class OrderBillingAddress(UniversalBaseModel): @@ -21,31 +21,28 @@ class OrderBillingAddress(UniversalBaseModel): """ japan_type: typing_extensions.Annotated[ - typing.Optional[OrderBillingAddressJapanType], FieldMetadata(alias="japanType") - ] = pydantic.Field(default=None) - """ - Represents a Japan-only address format. This field will only appear on orders placed from Japan. - """ - + typing.Optional[OrderBillingAddressJapanType], + FieldMetadata(alias="japanType"), + pydantic.Field( + alias="japanType", + description="Represents a Japan-only address format. This field will only appear on orders placed from Japan.", + ), + ] = None addressee: typing.Optional[str] = pydantic.Field(default=None) """ Display name on the address """ - line_1: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line1")] = pydantic.Field( - default=None - ) - """ - The first line of the address - """ - - line_2: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line2")] = pydantic.Field( - default=None - ) - """ - The second line of the address - """ - + line_1: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="line1"), + pydantic.Field(alias="line1", description="The first line of the address"), + ] = None + line_2: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="line2"), + pydantic.Field(alias="line2", description="The second line of the address"), + ] = None city: typing.Optional[str] = pydantic.Field(default=None) """ The city of the address. @@ -61,12 +58,11 @@ class OrderBillingAddress(UniversalBaseModel): The country of the address """ - postal_code: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="postalCode")] = pydantic.Field( - default=None - ) - """ - The postal code of the address - """ + postal_code: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="postalCode"), + pydantic.Field(alias="postalCode", description="The postal code of the address"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/order_customer_info.py b/src/webflow/types/order_customer_info.py index 2179d43..fe7d88c 100644 --- a/src/webflow/types/order_customer_info.py +++ b/src/webflow/types/order_customer_info.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class OrderCustomerInfo(UniversalBaseModel): @@ -13,13 +13,11 @@ class OrderCustomerInfo(UniversalBaseModel): An object with the keys `fullName` and `email`. """ - full_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="fullName")] = pydantic.Field( - default=None - ) - """ - The full name of the Customer - """ - + full_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="fullName"), + pydantic.Field(alias="fullName", description="The full name of the Customer"), + ] = None email: typing.Optional[str] = pydantic.Field(default=None) """ The Customer's email address diff --git a/src/webflow/types/order_download_files_item.py b/src/webflow/types/order_download_files_item.py index bb0b489..1b54068 100644 --- a/src/webflow/types/order_download_files_item.py +++ b/src/webflow/types/order_download_files_item.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class OrderDownloadFilesItem(UniversalBaseModel): diff --git a/src/webflow/types/order_list.py b/src/webflow/types/order_list.py index 7e01a45..2ecc568 100644 --- a/src/webflow/types/order_list.py +++ b/src/webflow/types/order_list.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .order import Order + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .order import Order from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class OrderList(UniversalBaseModel): diff --git a/src/webflow/types/order_metadata.py b/src/webflow/types/order_metadata.py index 6b6de11..33d966b 100644 --- a/src/webflow/types/order_metadata.py +++ b/src/webflow/types/order_metadata.py @@ -1,15 +1,17 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class OrderMetadata(UniversalBaseModel): - is_buy_now: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isBuyNow")] = None + is_buy_now: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="isBuyNow"), pydantic.Field(alias="isBuyNow") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/order_price.py b/src/webflow/types/order_price.py index 6414850..310ea28 100644 --- a/src/webflow/types/order_price.py +++ b/src/webflow/types/order_price.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class OrderPrice(UniversalBaseModel): diff --git a/src/webflow/types/order_purchased_item.py b/src/webflow/types/order_purchased_item.py index ba51f76..01b815e 100644 --- a/src/webflow/types/order_purchased_item.py +++ b/src/webflow/types/order_purchased_item.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions -from .order_price import OrderPrice +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata +from .order_price import OrderPrice from .order_purchased_item_variant_image import OrderPurchasedItemVariantImage -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class OrderPurchasedItem(UniversalBaseModel): @@ -20,72 +20,56 @@ class OrderPurchasedItem(UniversalBaseModel): Number of Item purchased. """ - row_total: typing_extensions.Annotated[typing.Optional[OrderPrice], FieldMetadata(alias="rowTotal")] = ( - pydantic.Field(default=None) - ) - """ - The total for the row - """ - - product_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="productId")] = pydantic.Field( - default=None - ) - """ - The unique identifier for the Product - """ - - product_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="productName")] = ( - pydantic.Field(default=None) - ) - """ - User-facing name of the Product - """ - - product_slug: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="productSlug")] = ( - pydantic.Field(default=None) - ) - """ - Slug for the Product - """ - - variant_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="variantId")] = pydantic.Field( - default=None - ) - """ - Identifier for the Product Variant (SKU) - """ - - variant_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="variantName")] = ( - pydantic.Field(default=None) - ) - """ - User-facing name of the Product Variant (SKU) - """ - - variant_slug: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="variantSlug")] = ( - pydantic.Field(default=None) - ) - """ - Slug for the Product Variant (SKU) - """ - - variant_sku: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="variantSKU")] = pydantic.Field( - default=None - ) - """ - The user-defined custom SKU of the Product Variant (SKU) - """ - + row_total: typing_extensions.Annotated[ + typing.Optional[OrderPrice], + FieldMetadata(alias="rowTotal"), + pydantic.Field(alias="rowTotal", description="The total for the row"), + ] = None + product_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="productId"), + pydantic.Field(alias="productId", description="The unique identifier for the Product"), + ] = None + product_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="productName"), + pydantic.Field(alias="productName", description="User-facing name of the Product"), + ] = None + product_slug: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="productSlug"), + pydantic.Field(alias="productSlug", description="Slug for the Product"), + ] = None + variant_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="variantId"), + pydantic.Field(alias="variantId", description="Identifier for the Product Variant (SKU)"), + ] = None + variant_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="variantName"), + pydantic.Field(alias="variantName", description="User-facing name of the Product Variant (SKU)"), + ] = None + variant_slug: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="variantSlug"), + pydantic.Field(alias="variantSlug", description="Slug for the Product Variant (SKU)"), + ] = None + variant_sku: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="variantSKU"), + pydantic.Field(alias="variantSKU", description="The user-defined custom SKU of the Product Variant (SKU)"), + ] = None variant_image: typing_extensions.Annotated[ - typing.Optional[OrderPurchasedItemVariantImage], FieldMetadata(alias="variantImage") + typing.Optional[OrderPurchasedItemVariantImage], + FieldMetadata(alias="variantImage"), + pydantic.Field(alias="variantImage"), + ] = None + variant_price: typing_extensions.Annotated[ + typing.Optional[OrderPrice], + FieldMetadata(alias="variantPrice"), + pydantic.Field(alias="variantPrice", description="The price corresponding to the variant"), ] = None - variant_price: typing_extensions.Annotated[typing.Optional[OrderPrice], FieldMetadata(alias="variantPrice")] = ( - pydantic.Field(default=None) - ) - """ - The price corresponding to the variant - """ - weight: typing.Optional[float] = pydantic.Field(default=None) """ The physical weight of the variant if provided, or null diff --git a/src/webflow/types/order_purchased_item_variant_image.py b/src/webflow/types/order_purchased_item_variant_image.py index 1444bdd..14b745f 100644 --- a/src/webflow/types/order_purchased_item_variant_image.py +++ b/src/webflow/types/order_purchased_item_variant_image.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .order_purchased_item_variant_image_file import OrderPurchasedItemVariantImageFile -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class OrderPurchasedItemVariantImage(UniversalBaseModel): diff --git a/src/webflow/types/order_purchased_item_variant_image_file.py b/src/webflow/types/order_purchased_item_variant_image_file.py index e61c891..0dc2670 100644 --- a/src/webflow/types/order_purchased_item_variant_image_file.py +++ b/src/webflow/types/order_purchased_item_variant_image_file.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt from .order_purchased_item_variant_image_file_variants_item import OrderPurchasedItemVariantImageFileVariantsItem -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class OrderPurchasedItemVariantImageFile(UniversalBaseModel): @@ -16,27 +16,21 @@ class OrderPurchasedItemVariantImageFile(UniversalBaseModel): The image size in bytes """ - original_file_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="originalFileName")] = ( - pydantic.Field(default=None) - ) - """ - the original name of the image - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - The creation timestamp of the image - """ - - content_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="contentType")] = ( - pydantic.Field(default=None) - ) - """ - The MIME type of the image - """ - + original_file_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="originalFileName"), + pydantic.Field(alias="originalFileName", description="the original name of the image"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The creation timestamp of the image"), + ] = None + content_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="contentType"), + pydantic.Field(alias="contentType", description="The MIME type of the image"), + ] = None width: typing.Optional[int] = pydantic.Field(default=None) """ The image width in pixels diff --git a/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py b/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py index a49bb84..093c7df 100644 --- a/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py +++ b/src/webflow/types/order_purchased_item_variant_image_file_variants_item.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class OrderPurchasedItemVariantImageFileVariantsItem(UniversalBaseModel): @@ -14,9 +14,9 @@ class OrderPurchasedItemVariantImageFileVariantsItem(UniversalBaseModel): The hosted location for the Variant's image """ - original_file_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="originalFileName")] = ( - None - ) + original_file_name: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="originalFileName"), pydantic.Field(alias="originalFileName") + ] = None size: typing.Optional[float] = pydantic.Field(default=None) """ The image size in bytes diff --git a/src/webflow/types/order_shipping_address.py b/src/webflow/types/order_shipping_address.py index 5c62f00..afa230a 100644 --- a/src/webflow/types/order_shipping_address.py +++ b/src/webflow/types/order_shipping_address.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .order_shipping_address_type import OrderShippingAddressType + import pydantic import typing_extensions -from .order_shipping_address_japan_type import OrderShippingAddressJapanType +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .order_shipping_address_japan_type import OrderShippingAddressJapanType +from .order_shipping_address_type import OrderShippingAddressType class OrderShippingAddress(UniversalBaseModel): @@ -21,31 +21,28 @@ class OrderShippingAddress(UniversalBaseModel): """ japan_type: typing_extensions.Annotated[ - typing.Optional[OrderShippingAddressJapanType], FieldMetadata(alias="japanType") - ] = pydantic.Field(default=None) - """ - Represents a Japan-only address format. This field will only appear on orders placed from Japan. - """ - + typing.Optional[OrderShippingAddressJapanType], + FieldMetadata(alias="japanType"), + pydantic.Field( + alias="japanType", + description="Represents a Japan-only address format. This field will only appear on orders placed from Japan.", + ), + ] = None addressee: typing.Optional[str] = pydantic.Field(default=None) """ Display name on the address """ - line_1: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line1")] = pydantic.Field( - default=None - ) - """ - The first line of the address - """ - - line_2: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="line2")] = pydantic.Field( - default=None - ) - """ - The second line of the address - """ - + line_1: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="line1"), + pydantic.Field(alias="line1", description="The first line of the address"), + ] = None + line_2: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="line2"), + pydantic.Field(alias="line2", description="The second line of the address"), + ] = None city: typing.Optional[str] = pydantic.Field(default=None) """ The city of the address. @@ -61,12 +58,11 @@ class OrderShippingAddress(UniversalBaseModel): The country of the address """ - postal_code: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="postalCode")] = pydantic.Field( - default=None - ) - """ - The postal code of the address - """ + postal_code: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="postalCode"), + pydantic.Field(alias="postalCode", description="The postal code of the address"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/order_totals.py b/src/webflow/types/order_totals.py index 3abdc2e..deca73c 100644 --- a/src/webflow/types/order_totals.py +++ b/src/webflow/types/order_totals.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .order_price import OrderPrice + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .order_price import OrderPrice from .order_totals_extras_item import OrderTotalsExtrasItem -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class OrderTotals(UniversalBaseModel): diff --git a/src/webflow/types/order_totals_extras_item.py b/src/webflow/types/order_totals_extras_item.py index fa71f2f..55f9f65 100644 --- a/src/webflow/types/order_totals_extras_item.py +++ b/src/webflow/types/order_totals_extras_item.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .order_totals_extras_item_type import OrderTotalsExtrasItemType + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .order_price import OrderPrice -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .order_totals_extras_item_type import OrderTotalsExtrasItemType class OrderTotalsExtrasItem(UniversalBaseModel): diff --git a/src/webflow/types/page.py b/src/webflow/types/page.py index 51346a0..f191daa 100644 --- a/src/webflow/types/page.py +++ b/src/webflow/types/page.py @@ -1,14 +1,14 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt +import typing + import pydantic import typing_extensions -import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt -from .page_seo import PageSeo from .page_open_graph import PageOpenGraph -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .page_seo import PageSeo class Page(UniversalBaseModel): @@ -21,13 +21,11 @@ class Page(UniversalBaseModel): Unique identifier for the Page """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - Unique identifier for the Site - """ - + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="Unique identifier for the Site"), + ] = None title: typing.Optional[str] = pydantic.Field(default=None) """ Title of the Page @@ -38,34 +36,29 @@ class Page(UniversalBaseModel): slug of the Page (derived from title) """ - parent_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="parentId")] = pydantic.Field( - default=None - ) - """ - Identifier of the parent folder - """ - - collection_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="collectionId")] = ( - pydantic.Field(default=None) - ) - """ - Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection. - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - The date the Page was created - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the Page was most recently updated - """ - + parent_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="parentId"), + pydantic.Field(alias="parentId", description="Identifier of the parent folder"), + ] = None + collection_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="collectionId"), + pydantic.Field( + alias="collectionId", + description="Unique identifier for a linked Collection, value will be null if the Page is not part of a Collection.", + ), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the Page was created"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the Page was most recently updated"), + ] = None archived: typing.Optional[bool] = pydantic.Field(default=None) """ Whether the Page has been archived @@ -76,52 +69,49 @@ class Page(UniversalBaseModel): Whether the Page is a draft """ - can_branch: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="canBranch")] = pydantic.Field( - default=None - ) - """ - Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching). Pages that are already branches cannot be branched again. - """ - - is_branch: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isBranch")] = pydantic.Field( - default=None - ) - """ - Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching) - """ - - branch_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="branchId")] = pydantic.Field( - default=None - ) - """ - If the Page is a Branch of another Page, this is the ID of the Branch - """ - + can_branch: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="canBranch"), + pydantic.Field( + alias="canBranch", + description="Indicates whether the Page supports [Page Branching](https://university.webflow.com/lesson/page-branching). Pages that are already branches cannot be branched again.", + ), + ] = None + is_branch: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isBranch"), + pydantic.Field( + alias="isBranch", + description="Indicates whether the Page is a Branch of another Page [Page Branching](https://university.webflow.com/lesson/page-branching)", + ), + ] = None + branch_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="branchId"), + pydantic.Field( + alias="branchId", description="If the Page is a Branch of another Page, this is the ID of the Branch" + ), + ] = None seo: typing.Optional[PageSeo] = pydantic.Field(default=None) """ SEO-related fields for the Page """ - open_graph: typing_extensions.Annotated[typing.Optional[PageOpenGraph], FieldMetadata(alias="openGraph")] = ( - pydantic.Field(default=None) - ) - """ - Open Graph fields for the Page - """ - - locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="localeId")] = pydantic.Field( - default=None - ) - """ - Unique ID of the page locale - """ - - published_path: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="publishedPath")] = ( - pydantic.Field(default=None) - ) - """ - Relative path of the published page URL - """ + open_graph: typing_extensions.Annotated[ + typing.Optional[PageOpenGraph], + FieldMetadata(alias="openGraph"), + pydantic.Field(alias="openGraph", description="Open Graph fields for the Page"), + ] = None + locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="localeId"), + pydantic.Field(alias="localeId", description="Unique ID of the page locale"), + ] = None + published_path: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="publishedPath"), + pydantic.Field(alias="publishedPath", description="Relative path of the published page URL"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/page_created_webhook.py b/src/webflow/types/page_created_webhook.py index 60ef73e..14efaf3 100644 --- a/src/webflow/types/page_created_webhook.py +++ b/src/webflow/types/page_created_webhook.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .page_created_webhook_payload import PageCreatedWebhookPayload -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class PageCreatedWebhook(UniversalBaseModel): @@ -14,13 +14,11 @@ class PageCreatedWebhook(UniversalBaseModel): The Webhook payload for when a Page is created """ - trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( - pydantic.Field(default=None) - ) - """ - The type of event that triggered the request - """ - + trigger_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = None payload: typing.Optional[PageCreatedWebhookPayload] = pydantic.Field(default=None) """ The payload of data sent from Webflow diff --git a/src/webflow/types/page_created_webhook_payload.py b/src/webflow/types/page_created_webhook_payload.py index e986315..4dd3385 100644 --- a/src/webflow/types/page_created_webhook_payload.py +++ b/src/webflow/types/page_created_webhook_payload.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions -import typing -from ..core.serialization import FieldMetadata import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class PageCreatedWebhookPayload(UniversalBaseModel): @@ -14,11 +14,21 @@ class PageCreatedWebhookPayload(UniversalBaseModel): The payload of data sent from Webflow """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = None - page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = None - page_title: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageTitle")] = None - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None - published_path: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="publishedPath")] = None + site_id: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="siteId"), pydantic.Field(alias="siteId") + ] = None + page_id: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="pageId"), pydantic.Field(alias="pageId") + ] = None + page_title: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="pageTitle"), pydantic.Field(alias="pageTitle") + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="createdOn"), pydantic.Field(alias="createdOn") + ] = None + published_path: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="publishedPath"), pydantic.Field(alias="publishedPath") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/page_deleted_webhook.py b/src/webflow/types/page_deleted_webhook.py index 5894078..247f4ae 100644 --- a/src/webflow/types/page_deleted_webhook.py +++ b/src/webflow/types/page_deleted_webhook.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .page_deleted_webhook_payload import PageDeletedWebhookPayload -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class PageDeletedWebhook(UniversalBaseModel): @@ -14,13 +14,11 @@ class PageDeletedWebhook(UniversalBaseModel): The Webhook payload for when a Page is deleted """ - trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( - pydantic.Field(default=None) - ) - """ - The type of event that triggered the request - """ - + trigger_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = None payload: typing.Optional[PageDeletedWebhookPayload] = pydantic.Field(default=None) """ The payload of data sent from Webflow diff --git a/src/webflow/types/page_deleted_webhook_payload.py b/src/webflow/types/page_deleted_webhook_payload.py index 5d09458..e78f589 100644 --- a/src/webflow/types/page_deleted_webhook_payload.py +++ b/src/webflow/types/page_deleted_webhook_payload.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions -import typing -from ..core.serialization import FieldMetadata import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class PageDeletedWebhookPayload(UniversalBaseModel): @@ -14,11 +14,21 @@ class PageDeletedWebhookPayload(UniversalBaseModel): The payload of data sent from Webflow """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = None - page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = None - page_title: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageTitle")] = None - deleted_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="deletedOn")] = None - published_path: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="publishedPath")] = None + site_id: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="siteId"), pydantic.Field(alias="siteId") + ] = None + page_id: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="pageId"), pydantic.Field(alias="pageId") + ] = None + page_title: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="pageTitle"), pydantic.Field(alias="pageTitle") + ] = None + deleted_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="deletedOn"), pydantic.Field(alias="deletedOn") + ] = None + published_path: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="publishedPath"), pydantic.Field(alias="publishedPath") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/page_list.py b/src/webflow/types/page_list.py index 59e4e79..a392bea 100644 --- a/src/webflow/types/page_list.py +++ b/src/webflow/types/page_list.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .page import Page from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class PageList(UniversalBaseModel): diff --git a/src/webflow/types/page_metadata_updated_webhook.py b/src/webflow/types/page_metadata_updated_webhook.py index 1bcb1e1..0751f3a 100644 --- a/src/webflow/types/page_metadata_updated_webhook.py +++ b/src/webflow/types/page_metadata_updated_webhook.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .page_metadata_updated_webhook_payload import PageMetadataUpdatedWebhookPayload -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class PageMetadataUpdatedWebhook(UniversalBaseModel): @@ -14,13 +14,11 @@ class PageMetadataUpdatedWebhook(UniversalBaseModel): The Webhook payload for when a Page's metadata is updated """ - trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( - pydantic.Field(default=None) - ) - """ - The type of event that triggered the request - """ - + trigger_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = None payload: typing.Optional[PageMetadataUpdatedWebhookPayload] = pydantic.Field(default=None) """ The payload of data sent from Webflow diff --git a/src/webflow/types/page_metadata_updated_webhook_payload.py b/src/webflow/types/page_metadata_updated_webhook_payload.py index a75b703..d71cf47 100644 --- a/src/webflow/types/page_metadata_updated_webhook_payload.py +++ b/src/webflow/types/page_metadata_updated_webhook_payload.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions -import typing -from ..core.serialization import FieldMetadata import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class PageMetadataUpdatedWebhookPayload(UniversalBaseModel): @@ -14,11 +14,21 @@ class PageMetadataUpdatedWebhookPayload(UniversalBaseModel): The payload of data sent from Webflow """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = None - page_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageId")] = None - page_title: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pageTitle")] = None - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None - published_path: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="publishedPath")] = None + site_id: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="siteId"), pydantic.Field(alias="siteId") + ] = None + page_id: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="pageId"), pydantic.Field(alias="pageId") + ] = None + page_title: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="pageTitle"), pydantic.Field(alias="pageTitle") + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated"), pydantic.Field(alias="lastUpdated") + ] = None + published_path: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="publishedPath"), pydantic.Field(alias="publishedPath") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/page_open_graph.py b/src/webflow/types/page_open_graph.py index f6d48b1..63d6898 100644 --- a/src/webflow/types/page_open_graph.py +++ b/src/webflow/types/page_open_graph.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class PageOpenGraph(UniversalBaseModel): @@ -18,24 +18,24 @@ class PageOpenGraph(UniversalBaseModel): The title supplied to Open Graph annotations """ - title_copied: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="titleCopied")] = ( - pydantic.Field(default=None) - ) - """ - Indicates the Open Graph title was copied from the SEO title - """ - + title_copied: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="titleCopied"), + pydantic.Field(alias="titleCopied", description="Indicates the Open Graph title was copied from the SEO title"), + ] = None description: typing.Optional[str] = pydantic.Field(default=None) """ The description supplied to Open Graph annotations """ - description_copied: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="descriptionCopied")] = ( - pydantic.Field(default=None) - ) - """ - Indicates the Open Graph description was copied from the SEO description - """ + description_copied: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="descriptionCopied"), + pydantic.Field( + alias="descriptionCopied", + description="Indicates the Open Graph description was copied from the SEO description", + ), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/page_seo.py b/src/webflow/types/page_seo.py index 737e68c..4182b16 100644 --- a/src/webflow/types/page_seo.py +++ b/src/webflow/types/page_seo.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class PageSeo(UniversalBaseModel): diff --git a/src/webflow/types/pagination.py b/src/webflow/types/pagination.py index 82e650c..72cd209 100644 --- a/src/webflow/types/pagination.py +++ b/src/webflow/types/pagination.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class Pagination(UniversalBaseModel): diff --git a/src/webflow/types/payload.py b/src/webflow/types/payload.py index a608741..efd0d48 100644 --- a/src/webflow/types/payload.py +++ b/src/webflow/types/payload.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt from .payload_field_data import PayloadFieldData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Payload(UniversalBaseModel): @@ -20,42 +20,44 @@ class Payload(UniversalBaseModel): The ID of the collection item that was unpublished """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - The ID of the site - """ - - workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( - pydantic.Field(default=None) - ) - """ - The ID of the workspace - """ - - collection_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="collectionId")] = ( - pydantic.Field(default=None) - ) - """ - The ID of the collection - """ - - cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( - pydantic.Field(default=None) - ) - """ - Unique identifier of the CMS locale for this item - """ - - last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( - None - ) - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None - is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None - is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None - field_data: typing_extensions.Annotated[typing.Optional[PayloadFieldData], FieldMetadata(alias="fieldData")] = None + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="The ID of the site"), + ] = None + workspace_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="workspaceId"), + pydantic.Field(alias="workspaceId", description="The ID of the workspace"), + ] = None + collection_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="collectionId"), + pydantic.Field(alias="collectionId", description="The ID of the collection"), + ] = None + cms_locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="cmsLocaleId"), + pydantic.Field(alias="cmsLocaleId", description="Unique identifier of the CMS locale for this item"), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished"), pydantic.Field(alias="lastPublished") + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated"), pydantic.Field(alias="lastUpdated") + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="createdOn"), pydantic.Field(alias="createdOn") + ] = None + is_archived: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="isArchived"), pydantic.Field(alias="isArchived") + ] = None + is_draft: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="isDraft"), pydantic.Field(alias="isDraft") + ] = None + field_data: typing_extensions.Annotated[ + typing.Optional[PayloadFieldData], FieldMetadata(alias="fieldData"), pydantic.Field(alias="fieldData") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/payload_field_data.py b/src/webflow/types/payload_field_data.py index 6fa4fc5..c8c69ce 100644 --- a/src/webflow/types/payload_field_data.py +++ b/src/webflow/types/payload_field_data.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class PayloadFieldData(UniversalBaseModel): diff --git a/src/webflow/types/paypal_details.py b/src/webflow/types/paypal_details.py index b98efef..9ed4a6e 100644 --- a/src/webflow/types/paypal_details.py +++ b/src/webflow/types/paypal_details.py @@ -1,55 +1,44 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class PaypalDetails(UniversalBaseModel): - order_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="orderId")] = pydantic.Field( - default=None - ) - """ - PayPal order identifier - """ - - payer_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="payerId")] = pydantic.Field( - default=None - ) - """ - PayPal payer identifier - """ - - capture_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="captureId")] = pydantic.Field( - default=None - ) - """ - PayPal capture identifier - """ - - refund_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="refundId")] = pydantic.Field( - default=None - ) - """ - PayPal refund identifier - """ - - refund_reason: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="refundReason")] = ( - pydantic.Field(default=None) - ) - """ - PayPal-issued reason for the refund - """ - - dispute_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="disputeId")] = pydantic.Field( - default=None - ) - """ - PayPal dispute identifier - """ + order_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="orderId"), + pydantic.Field(alias="orderId", description="PayPal order identifier"), + ] = None + payer_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="payerId"), + pydantic.Field(alias="payerId", description="PayPal payer identifier"), + ] = None + capture_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="captureId"), + pydantic.Field(alias="captureId", description="PayPal capture identifier"), + ] = None + refund_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="refundId"), + pydantic.Field(alias="refundId", description="PayPal refund identifier"), + ] = None + refund_reason: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="refundReason"), + pydantic.Field(alias="refundReason", description="PayPal-issued reason for the refund"), + ] = None + dispute_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="disputeId"), + pydantic.Field(alias="disputeId", description="PayPal dispute identifier"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/product.py b/src/webflow/types/product.py index a39ca3d..f0e48bd 100644 --- a/src/webflow/types/product.py +++ b/src/webflow/types/product.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt from .product_field_data import ProductFieldData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Product(UniversalBaseModel): @@ -20,49 +20,39 @@ class Product(UniversalBaseModel): Unique identifier for the Product """ - cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( - pydantic.Field(default=None) - ) - """ - Identifier for the locale of the CMS item - """ - - last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( - pydantic.Field(default=None) - ) - """ - The date the Product was last published - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the Product was last updated - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - The date the Product was created - """ - - is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Product is set to archived - """ - - is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = pydantic.Field( - default=None - ) - """ - Boolean determining if the Product is set to draft - """ - - field_data: typing_extensions.Annotated[typing.Optional[ProductFieldData], FieldMetadata(alias="fieldData")] = None + cms_locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="cmsLocaleId"), + pydantic.Field(alias="cmsLocaleId", description="Identifier for the locale of the CMS item"), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastPublished"), + pydantic.Field(alias="lastPublished", description="The date the Product was last published"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the Product was last updated"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the Product was created"), + ] = None + is_archived: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isArchived"), + pydantic.Field(alias="isArchived", description="Boolean determining if the Product is set to archived"), + ] = None + is_draft: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isDraft"), + pydantic.Field(alias="isDraft", description="Boolean determining if the Product is set to draft"), + ] = None + field_data: typing_extensions.Annotated[ + typing.Optional[ProductFieldData], FieldMetadata(alias="fieldData"), pydantic.Field(alias="fieldData") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/product_and_sk_us.py b/src/webflow/types/product_and_sk_us.py index 6aea2cb..42b5b62 100644 --- a/src/webflow/types/product_and_sk_us.py +++ b/src/webflow/types/product_and_sk_us.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .product import Product from .sku import Sku -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class ProductAndSkUs(UniversalBaseModel): diff --git a/src/webflow/types/product_and_sk_us_list.py b/src/webflow/types/product_and_sk_us_list.py index 6bdafd5..a2060d7 100644 --- a/src/webflow/types/product_and_sk_us_list.py +++ b/src/webflow/types/product_and_sk_us_list.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .product_and_sk_us import ProductAndSkUs + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .product_and_sk_us import ProductAndSkUs class ProductAndSkUsList(UniversalBaseModel): diff --git a/src/webflow/types/product_field_data.py b/src/webflow/types/product_field_data.py index e907159..b9c15fb 100644 --- a/src/webflow/types/product_field_data.py +++ b/src/webflow/types/product_field_data.py @@ -1,19 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions -from .sku_property_list import SkuPropertyList +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from .product_field_data_tax_category import ProductFieldDataTaxCategory from .product_field_data_ec_product_type import ProductFieldDataEcProductType -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .product_field_data_tax_category import ProductFieldDataTaxCategory +from .sku_property_list import SkuPropertyList class ProductFieldData(UniversalBaseModel): """ - Contains content-specific details for a product, covering both standard (e.g., title, description) and custom fields tailored to the product setup. + Contains content-specific details for a product, covering both standard (e.g., title, description) and custom fields tailored to the product setup. """ name: typing.Optional[str] = pydantic.Field(default=None) @@ -37,37 +37,33 @@ class ProductFieldData(UniversalBaseModel): """ sku_properties: typing_extensions.Annotated[ - typing.Optional[typing.List[SkuPropertyList]], FieldMetadata(alias="sku-properties") - ] = pydantic.Field(default=None) - """ - Variant types to include in SKUs - """ - + typing.Optional[typing.List[SkuPropertyList]], + FieldMetadata(alias="sku-properties"), + pydantic.Field(alias="sku-properties", description="Variant types to include in SKUs"), + ] = None category: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ The category your product belongs to. """ tax_category: typing_extensions.Annotated[ - typing.Optional[ProductFieldDataTaxCategory], FieldMetadata(alias="tax-category") - ] = pydantic.Field(default=None) - """ - Product tax class - """ - - default_sku: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="default-sku")] = pydantic.Field( - default=None - ) - """ - The default SKU associated with this product. - """ - + typing.Optional[ProductFieldDataTaxCategory], + FieldMetadata(alias="tax-category"), + pydantic.Field(alias="tax-category", description="Product tax class"), + ] = None + default_sku: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="default-sku"), + pydantic.Field(alias="default-sku", description="The default SKU associated with this product."), + ] = None ec_product_type: typing_extensions.Annotated[ - typing.Optional[ProductFieldDataEcProductType], FieldMetadata(alias="ec-product-type") - ] = pydantic.Field(default=None) - """ - Product types. Enums reflect the following values in order: Physical, Digital, Service, Advanced" - """ + typing.Optional[ProductFieldDataEcProductType], + FieldMetadata(alias="ec-product-type"), + pydantic.Field( + alias="ec-product-type", + description='Product types. Enums reflect the following values in order: Physical, Digital, Service, Advanced"', + ), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/redirect.py b/src/webflow/types/redirect.py index 0205f34..4937365 100644 --- a/src/webflow/types/redirect.py +++ b/src/webflow/types/redirect.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Redirect(UniversalBaseModel): @@ -18,19 +18,16 @@ class Redirect(UniversalBaseModel): The ID of the specific redirect rule """ - from_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="fromUrl")] = pydantic.Field( - default=None - ) - """ - The source URL path that will be redirected. - """ - - to_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="toUrl")] = pydantic.Field( - default=None - ) - """ - The target URL path where the user or client will be redirected. - """ + from_url: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="fromUrl"), + pydantic.Field(alias="fromUrl", description="The source URL path that will be redirected."), + ] = None + to_url: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="toUrl"), + pydantic.Field(alias="toUrl", description="The target URL path where the user or client will be redirected."), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/redirects.py b/src/webflow/types/redirects.py index bd466b2..5126ce1 100644 --- a/src/webflow/types/redirects.py +++ b/src/webflow/types/redirects.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .redirect import Redirect + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .redirect import Redirect class Redirects(UniversalBaseModel): diff --git a/src/webflow/types/reference_field.py b/src/webflow/types/reference_field.py index 3c75552..fa2efe6 100644 --- a/src/webflow/types/reference_field.py +++ b/src/webflow/types/reference_field.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from .reference_field_type import ReferenceFieldType from .reference_field_metadata import ReferenceFieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .reference_field_type import ReferenceFieldType class ReferenceField(UniversalBaseModel): @@ -16,37 +16,29 @@ class ReferenceField(UniversalBaseModel): Unique identifier for a Field """ - is_editable: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEditable")] = pydantic.Field( - default=None - ) - """ - Define whether the field is editable - """ - - is_required: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isRequired")] = pydantic.Field( - default=None - ) - """ - define whether a field is required in a collection - """ - + is_editable: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isEditable"), + pydantic.Field(alias="isEditable", description="Define whether the field is editable"), + ] = None + is_required: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isRequired"), + pydantic.Field(alias="isRequired", description="define whether a field is required in a collection"), + ] = None type: ReferenceFieldType = pydantic.Field() """ Choose these appropriate field type for your collection data """ - display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() - """ - The name of a field - """ - - help_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="helpText")] = pydantic.Field( - default=None - ) - """ - Additional text to help anyone filling out this field - """ - + display_name: typing_extensions.Annotated[ + str, FieldMetadata(alias="displayName"), pydantic.Field(alias="displayName", description="The name of a field") + ] + help_text: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="helpText"), + pydantic.Field(alias="helpText", description="Additional text to help anyone filling out this field"), + ] = None metadata: ReferenceFieldMetadata = pydantic.Field() """ The collectionId for the referenced collection. Only applicable for Reference and MultiReference fields. diff --git a/src/webflow/types/reference_field_metadata.py b/src/webflow/types/reference_field_metadata.py index 164c4a6..0a6bb01 100644 --- a/src/webflow/types/reference_field_metadata.py +++ b/src/webflow/types/reference_field_metadata.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import typing class ReferenceFieldMetadata(UniversalBaseModel): @@ -13,10 +13,11 @@ class ReferenceFieldMetadata(UniversalBaseModel): The collectionId for the referenced collection. Only applicable for Reference and MultiReference fields. """ - collection_id: typing_extensions.Annotated[str, FieldMetadata(alias="collectionId")] = pydantic.Field() - """ - The unique identifier of the collection - """ + collection_id: typing_extensions.Annotated[ + str, + FieldMetadata(alias="collectionId"), + pydantic.Field(alias="collectionId", description="The unique identifier of the collection"), + ] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/registered_script_list.py b/src/webflow/types/registered_script_list.py index e9d8a01..8822e68 100644 --- a/src/webflow/types/registered_script_list.py +++ b/src/webflow/types/registered_script_list.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .custom_code_hosted_response import CustomCodeHostedResponse + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata +from .custom_code_hosted_response import CustomCodeHostedResponse from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class RegisteredScriptList(UniversalBaseModel): @@ -16,7 +16,9 @@ class RegisteredScriptList(UniversalBaseModel): """ registered_scripts: typing_extensions.Annotated[ - typing.Optional[typing.List[CustomCodeHostedResponse]], FieldMetadata(alias="registeredScripts") + typing.Optional[typing.List[CustomCodeHostedResponse]], + FieldMetadata(alias="registeredScripts"), + pydantic.Field(alias="registeredScripts"), ] = None pagination: typing.Optional[Pagination] = None diff --git a/src/webflow/types/robots.py b/src/webflow/types/robots.py index 7489660..6a6170e 100644 --- a/src/webflow/types/robots.py +++ b/src/webflow/types/robots.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .robots_rules_item import RobotsRulesItem + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .robots_rules_item import RobotsRulesItem class Robots(UniversalBaseModel): diff --git a/src/webflow/types/robots_rules_item.py b/src/webflow/types/robots_rules_item.py index 048f239..27c8a5e 100644 --- a/src/webflow/types/robots_rules_item.py +++ b/src/webflow/types/robots_rules_item.py @@ -1,19 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class RobotsRulesItem(UniversalBaseModel): - user_agent: typing_extensions.Annotated[str, FieldMetadata(alias="userAgent")] = pydantic.Field() - """ - The user agent the rules apply to. - """ - + user_agent: typing_extensions.Annotated[ + str, + FieldMetadata(alias="userAgent"), + pydantic.Field(alias="userAgent", description="The user agent the rules apply to."), + ] allows: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ List of paths allowed for this user agent. diff --git a/src/webflow/types/script_apply.py b/src/webflow/types/script_apply.py index 6ba1930..e2bd746 100644 --- a/src/webflow/types/script_apply.py +++ b/src/webflow/types/script_apply.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .script_apply_location import ScriptApplyLocation -import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class ScriptApply(UniversalBaseModel): @@ -23,7 +23,7 @@ class ScriptApply(UniversalBaseModel): Semantic Version String for the registered script *e.g. 0.0.1* """ - attributes: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) + attributes: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None) """ Developer-specified key/value pairs to be applied as attributes to the script """ diff --git a/src/webflow/types/script_apply_list.py b/src/webflow/types/script_apply_list.py index e89b54d..89c79f4 100644 --- a/src/webflow/types/script_apply_list.py +++ b/src/webflow/types/script_apply_list.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .script_apply import ScriptApply + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .script_apply import ScriptApply class ScriptApplyList(UniversalBaseModel): @@ -15,19 +15,16 @@ class ScriptApplyList(UniversalBaseModel): A list of scripts applied to a Site or a Page """ - last_updated: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - Date when the Site's scripts were last updated - """ - - created_on: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="createdOn")] = pydantic.Field( - default=None - ) - """ - Date when the Site's scripts were created - """ + last_updated: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="Date when the Site's scripts were last updated"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="Date when the Site's scripts were created"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/scripts.py b/src/webflow/types/scripts.py index 1f0c1c1..6ff9844 100644 --- a/src/webflow/types/scripts.py +++ b/src/webflow/types/scripts.py @@ -1,6 +1,7 @@ # This file was auto-generated by Fern from our API Definition. import typing + from .script_apply import ScriptApply Scripts = typing.List[ScriptApply] diff --git a/src/webflow/types/search_button_node.py b/src/webflow/types/search_button_node.py index 091b06c..7e40c75 100644 --- a/src/webflow/types/search_button_node.py +++ b/src/webflow/types/search_button_node.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class SearchButtonNode(UniversalBaseModel): diff --git a/src/webflow/types/search_button_node_write.py b/src/webflow/types/search_button_node_write.py index 15c5daf..532f4b3 100644 --- a/src/webflow/types/search_button_node_write.py +++ b/src/webflow/types/search_button_node_write.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import typing class SearchButtonNodeWrite(UniversalBaseModel): @@ -13,11 +13,9 @@ class SearchButtonNodeWrite(UniversalBaseModel): Update a search button node """ - node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() - """ - Node UUID - """ - + node_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="nodeId"), pydantic.Field(alias="nodeId", description="Node UUID") + ] value: str = pydantic.Field() """ The text content of the search button. diff --git a/src/webflow/types/select.py b/src/webflow/types/select.py index 7208091..d39d5c3 100644 --- a/src/webflow/types/select.py +++ b/src/webflow/types/select.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -import typing from .select_node_write_choices_item import SelectNodeWriteChoicesItem -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Select(UniversalBaseModel): @@ -14,11 +14,9 @@ class Select(UniversalBaseModel): Update choices on a select node """ - node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() - """ - Node UUID - """ - + node_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="nodeId"), pydantic.Field(alias="nodeId", description="Node UUID") + ] choices: typing.List[SelectNodeWriteChoicesItem] = pydantic.Field() """ The list of choices to set on the select node. diff --git a/src/webflow/types/select_node.py b/src/webflow/types/select_node.py index f8cc21f..17ca346 100644 --- a/src/webflow/types/select_node.py +++ b/src/webflow/types/select_node.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .select_node_choices_item import SelectNodeChoicesItem -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class SelectNode(UniversalBaseModel): diff --git a/src/webflow/types/select_node_choices_item.py b/src/webflow/types/select_node_choices_item.py index cd210b1..cb0bf0d 100644 --- a/src/webflow/types/select_node_choices_item.py +++ b/src/webflow/types/select_node_choices_item.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + class SelectNodeChoicesItem(UniversalBaseModel): value: str = pydantic.Field() diff --git a/src/webflow/types/select_node_write_choices_item.py b/src/webflow/types/select_node_write_choices_item.py index 4346fef..05f5108 100644 --- a/src/webflow/types/select_node_write_choices_item.py +++ b/src/webflow/types/select_node_write_choices_item.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + class SelectNodeWriteChoicesItem(UniversalBaseModel): value: str = pydantic.Field() diff --git a/src/webflow/types/setting_change.py b/src/webflow/types/setting_change.py index 8bbbb06..c2de45a 100644 --- a/src/webflow/types/setting_change.py +++ b/src/webflow/types/setting_change.py @@ -1,17 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .workspace_audit_log_item_payload_setting_change_method import WorkspaceAuditLogItemPayloadSettingChangeMethod -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class SettingChange(UniversalBaseModel): setting: typing.Optional[typing.Literal["ai_toggle"]] = None - previous_value: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousValue")] = None + previous_value: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="previousValue"), pydantic.Field(alias="previousValue") + ] = None value: typing.Optional[str] = None method: typing.Optional[WorkspaceAuditLogItemPayloadSettingChangeMethod] = None diff --git a/src/webflow/types/setting_change_audit_log_item.py b/src/webflow/types/setting_change_audit_log_item.py index 62b8579..6846347 100644 --- a/src/webflow/types/setting_change_audit_log_item.py +++ b/src/webflow/types/setting_change_audit_log_item.py @@ -1,17 +1,19 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .setting_change import SettingChange -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class SettingChangeAuditLogItem(UniversalBaseModel): event_sub_type: typing_extensions.Annotated[ - typing.Optional[typing.Literal["setting_updated"]], FieldMetadata(alias="eventSubType") + typing.Optional[typing.Literal["setting_updated"]], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[SettingChange] = None diff --git a/src/webflow/types/single_locale_created_payload.py b/src/webflow/types/single_locale_created_payload.py index 9293d8c..ea086d2 100644 --- a/src/webflow/types/single_locale_created_payload.py +++ b/src/webflow/types/single_locale_created_payload.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt +import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import typing -import datetime as dt from .single_locale_created_payload_field_data import SingleLocaleCreatedPayloadFieldData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class SingleLocaleCreatedPayload(UniversalBaseModel): @@ -16,36 +16,42 @@ class SingleLocaleCreatedPayload(UniversalBaseModel): Unique identifier for the Item """ - workspace_id: typing_extensions.Annotated[str, FieldMetadata(alias="workspaceId")] = pydantic.Field() - """ - Unique identifier of the workspace - """ - - site_id: typing_extensions.Annotated[str, FieldMetadata(alias="siteId")] = pydantic.Field() - """ - Unique identifier of the site - """ - - collection_id: typing_extensions.Annotated[str, FieldMetadata(alias="collectionId")] = pydantic.Field() - """ - Unique identifier of the collection - """ - - cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( - pydantic.Field(default=None) - ) - """ - Unique identifier of the CMS locale for this item - """ - - last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( - None - ) - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None - is_archived: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isArchived")] = None - is_draft: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isDraft")] = None - field_data: typing_extensions.Annotated[SingleLocaleCreatedPayloadFieldData, FieldMetadata(alias="fieldData")] + workspace_id: typing_extensions.Annotated[ + str, + FieldMetadata(alias="workspaceId"), + pydantic.Field(alias="workspaceId", description="Unique identifier of the workspace"), + ] + site_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="siteId"), pydantic.Field(alias="siteId", description="Unique identifier of the site") + ] + collection_id: typing_extensions.Annotated[ + str, + FieldMetadata(alias="collectionId"), + pydantic.Field(alias="collectionId", description="Unique identifier of the collection"), + ] + cms_locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="cmsLocaleId"), + pydantic.Field(alias="cmsLocaleId", description="Unique identifier of the CMS locale for this item"), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished"), pydantic.Field(alias="lastPublished") + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated"), pydantic.Field(alias="lastUpdated") + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="createdOn"), pydantic.Field(alias="createdOn") + ] = None + is_archived: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="isArchived"), pydantic.Field(alias="isArchived") + ] = None + is_draft: typing_extensions.Annotated[ + typing.Optional[bool], FieldMetadata(alias="isDraft"), pydantic.Field(alias="isDraft") + ] = None + field_data: typing_extensions.Annotated[ + SingleLocaleCreatedPayloadFieldData, FieldMetadata(alias="fieldData"), pydantic.Field(alias="fieldData") + ] if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/single_locale_created_payload_field_data.py b/src/webflow/types/single_locale_created_payload_field_data.py index b412ef9..7306bc9 100644 --- a/src/webflow/types/single_locale_created_payload_field_data.py +++ b/src/webflow/types/single_locale_created_payload_field_data.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class SingleLocaleCreatedPayloadFieldData(UniversalBaseModel): diff --git a/src/webflow/types/site.py b/src/webflow/types/site.py index 96f66a1..15a4826 100644 --- a/src/webflow/types/site.py +++ b/src/webflow/types/site.py @@ -1,15 +1,15 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt +import typing + import pydantic import typing_extensions -import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt from .domain import Domain from .locales import Locales from .site_data_collection_type import SiteDataCollectionType -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Site(UniversalBaseModel): @@ -18,86 +18,69 @@ class Site(UniversalBaseModel): Unique identifier for the Site """ - workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( - pydantic.Field(default=None) - ) - """ - Unique identifier for the Workspace - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - Date the Site was created - """ - - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = ( - pydantic.Field(default=None) - ) - """ - Name given to Site - """ - - short_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="shortName")] = pydantic.Field( - default=None - ) - """ - Slugified version of name - """ - - last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( - pydantic.Field(default=None) - ) - """ - Date the Site was last published - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - Date the Site was last updated - """ - - preview_url: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previewUrl")] = pydantic.Field( - default=None - ) - """ - URL of a generated image for the given Site - """ - - time_zone: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="timeZone")] = pydantic.Field( - default=None - ) - """ - Site timezone set under Site Settings - """ - - parent_folder_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="parentFolderId")] = ( - pydantic.Field(default=None) - ) - """ - The ID of the parent folder the Site exists in - """ - + workspace_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="workspaceId"), + pydantic.Field(alias="workspaceId", description="Unique identifier for the Workspace"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="Date the Site was created"), + ] = None + display_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="displayName"), + pydantic.Field(alias="displayName", description="Name given to Site"), + ] = None + short_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="shortName"), + pydantic.Field(alias="shortName", description="Slugified version of name"), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastPublished"), + pydantic.Field(alias="lastPublished", description="Date the Site was last published"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="Date the Site was last updated"), + ] = None + preview_url: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="previewUrl"), + pydantic.Field(alias="previewUrl", description="URL of a generated image for the given Site"), + ] = None + time_zone: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="timeZone"), + pydantic.Field(alias="timeZone", description="Site timezone set under Site Settings"), + ] = None + parent_folder_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="parentFolderId"), + pydantic.Field(alias="parentFolderId", description="The ID of the parent folder the Site exists in"), + ] = None custom_domains: typing_extensions.Annotated[ - typing.Optional[typing.List[Domain]], FieldMetadata(alias="customDomains") + typing.Optional[typing.List[Domain]], + FieldMetadata(alias="customDomains"), + pydantic.Field(alias="customDomains"), ] = None locales: typing.Optional[Locales] = None data_collection_enabled: typing_extensions.Annotated[ - typing.Optional[bool], FieldMetadata(alias="dataCollectionEnabled") - ] = pydantic.Field(default=None) - """ - Indicates if data collection is enabled for the site. - """ - + typing.Optional[bool], + FieldMetadata(alias="dataCollectionEnabled"), + pydantic.Field( + alias="dataCollectionEnabled", description="Indicates if data collection is enabled for the site." + ), + ] = None data_collection_type: typing_extensions.Annotated[ - typing.Optional[SiteDataCollectionType], FieldMetadata(alias="dataCollectionType") - ] = pydantic.Field(default=None) - """ - The type of data collection enabled for the site. - """ + typing.Optional[SiteDataCollectionType], + FieldMetadata(alias="dataCollectionType"), + pydantic.Field(alias="dataCollectionType", description="The type of data collection enabled for the site."), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/site_activity_log_item.py b/src/webflow/types/site_activity_log_item.py index 0ad70ea..cc07cef 100644 --- a/src/webflow/types/site_activity_log_item.py +++ b/src/webflow/types/site_activity_log_item.py @@ -1,31 +1,45 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + +import pydantic import typing_extensions -import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .site_activity_log_item_event import SiteActivityLogItemEvent from .site_activity_log_item_resource_operation import SiteActivityLogItemResourceOperation from .site_activity_log_item_user import SiteActivityLogItemUser -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class SiteActivityLogItem(UniversalBaseModel): id: typing.Optional[str] = None - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = None - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="createdOn"), pydantic.Field(alias="createdOn") + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated"), pydantic.Field(alias="lastUpdated") + ] = None event: typing.Optional[SiteActivityLogItemEvent] = None resource_operation: typing_extensions.Annotated[ - typing.Optional[SiteActivityLogItemResourceOperation], FieldMetadata(alias="resourceOperation") + typing.Optional[SiteActivityLogItemResourceOperation], + FieldMetadata(alias="resourceOperation"), + pydantic.Field(alias="resourceOperation"), ] = None user: typing.Optional[SiteActivityLogItemUser] = None - resource_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="resourceId")] = None - resource_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="resourceName")] = None - new_value: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="newValue")] = None - previous_value: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousValue")] = None - payload: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None + resource_id: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="resourceId"), pydantic.Field(alias="resourceId") + ] = None + resource_name: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="resourceName"), pydantic.Field(alias="resourceName") + ] = None + new_value: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="newValue"), pydantic.Field(alias="newValue") + ] = None + previous_value: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="previousValue"), pydantic.Field(alias="previousValue") + ] = None + payload: typing.Optional[typing.Dict[str, typing.Any]] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/site_activity_log_item_user.py b/src/webflow/types/site_activity_log_item_user.py index b372c65..82457cc 100644 --- a/src/webflow/types/site_activity_log_item_user.py +++ b/src/webflow/types/site_activity_log_item_user.py @@ -1,16 +1,18 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic class SiteActivityLogItemUser(UniversalBaseModel): id: typing.Optional[str] = None - display_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="displayName")] = None + display_name: typing_extensions.Annotated[ + typing.Optional[str], FieldMetadata(alias="displayName"), pydantic.Field(alias="displayName") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/site_activity_log_response.py b/src/webflow/types/site_activity_log_response.py index 32606a7..5d0cb51 100644 --- a/src/webflow/types/site_activity_log_response.py +++ b/src/webflow/types/site_activity_log_response.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .site_activity_log_item import SiteActivityLogItem -from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .pagination import Pagination +from .site_activity_log_item import SiteActivityLogItem class SiteActivityLogResponse(UniversalBaseModel): diff --git a/src/webflow/types/site_membership.py b/src/webflow/types/site_membership.py index 5ff933a..b9def86 100644 --- a/src/webflow/types/site_membership.py +++ b/src/webflow/types/site_membership.py @@ -1,49 +1,51 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .workspace_audit_log_item_payload_site_membership_site import WorkspaceAuditLogItemPayloadSiteMembershipSite + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata +from .workspace_audit_log_item_payload_site_membership_granular_access import ( + WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess, +) +from .workspace_audit_log_item_payload_site_membership_method import WorkspaceAuditLogItemPayloadSiteMembershipMethod +from .workspace_audit_log_item_payload_site_membership_site import WorkspaceAuditLogItemPayloadSiteMembershipSite from .workspace_audit_log_item_payload_site_membership_target_user import ( WorkspaceAuditLogItemPayloadSiteMembershipTargetUser, ) -from ..core.serialization import FieldMetadata -from .workspace_audit_log_item_payload_site_membership_method import WorkspaceAuditLogItemPayloadSiteMembershipMethod from .workspace_audit_log_item_payload_site_membership_user_type import ( WorkspaceAuditLogItemPayloadSiteMembershipUserType, ) -import pydantic -from .workspace_audit_log_item_payload_site_membership_granular_access import ( - WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess, -) -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class SiteMembership(UniversalBaseModel): site: typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipSite] = None target_user: typing_extensions.Annotated[ - typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipTargetUser], FieldMetadata(alias="targetUser") + typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipTargetUser], + FieldMetadata(alias="targetUser"), + pydantic.Field(alias="targetUser"), ] = None method: typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipMethod] = None user_type: typing_extensions.Annotated[ - typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipUserType], FieldMetadata(alias="userType") + typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipUserType], + FieldMetadata(alias="userType"), + pydantic.Field(alias="userType"), + ] = None + role_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="roleName"), + pydantic.Field(alias="roleName", description="The name of the role that was assigned to the user"), + ] = None + previous_role_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="previousRoleName"), + pydantic.Field(alias="previousRoleName", description="The previous role that the user had"), ] = None - role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( - default=None - ) - """ - The name of the role that was assigned to the user - """ - - previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( - pydantic.Field(default=None) - ) - """ - The previous role that the user had - """ - granular_access: typing_extensions.Annotated[ - typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess], FieldMetadata(alias="granularAccess") + typing.Optional[WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess], + FieldMetadata(alias="granularAccess"), + pydantic.Field(alias="granularAccess"), ] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/site_membership_audit_log_item.py b/src/webflow/types/site_membership_audit_log_item.py index d24ee9f..6bb4bc5 100644 --- a/src/webflow/types/site_membership_audit_log_item.py +++ b/src/webflow/types/site_membership_audit_log_item.py @@ -1,18 +1,20 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .site_membership import SiteMembership -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic +from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType class SiteMembershipAuditLogItem(UniversalBaseModel): event_sub_type: typing_extensions.Annotated[ - typing.Optional[SiteMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + typing.Optional[SiteMembershipAuditLogItemEventSubType], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[SiteMembership] = None diff --git a/src/webflow/types/site_plan.py b/src/webflow/types/site_plan.py index a8feecc..f008979 100644 --- a/src/webflow/types/site_plan.py +++ b/src/webflow/types/site_plan.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .site_plan_id import SitePlanId + import pydantic -from .site_plan_name import SitePlanName import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .site_plan_id import SitePlanId +from .site_plan_name import SitePlanName class SitePlan(UniversalBaseModel): @@ -21,12 +21,11 @@ class SitePlan(UniversalBaseModel): Name of the hosting plan. """ - pricing_info: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="pricingInfo")] = ( - pydantic.Field(default=None) - ) - """ - URL for more information about Webflow hosting plan pricing. - """ + pricing_info: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="pricingInfo"), + pydantic.Field(alias="pricingInfo", description="URL for more information about Webflow hosting plan pricing."), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/site_publish.py b/src/webflow/types/site_publish.py index 518178e..0e94156 100644 --- a/src/webflow/types/site_publish.py +++ b/src/webflow/types/site_publish.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .site_publish_payload import SitePublishPayload -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class SitePublish(UniversalBaseModel): @@ -14,13 +14,11 @@ class SitePublish(UniversalBaseModel): The Webhook payload for when a Site is published """ - trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( - pydantic.Field(default=None) - ) - """ - The type of event that triggered the request - """ - + trigger_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = None payload: typing.Optional[SitePublishPayload] = pydantic.Field(default=None) """ The payload of data sent from Webflow diff --git a/src/webflow/types/site_publish_payload.py b/src/webflow/types/site_publish_payload.py index f44882e..3e61145 100644 --- a/src/webflow/types/site_publish_payload.py +++ b/src/webflow/types/site_publish_payload.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions +import datetime as dt import typing -from ..core.serialization import FieldMetadata + import pydantic -import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class SitePublishPayload(UniversalBaseModel): @@ -14,31 +14,26 @@ class SitePublishPayload(UniversalBaseModel): The payload of data sent from Webflow """ - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - The ID of the site that was published - """ - - published_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="publishedOn")] = ( - pydantic.Field(default=None) - ) - """ - The timestamp of the publish event - """ - + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="The ID of the site that was published"), + ] = None + published_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="publishedOn"), + pydantic.Field(alias="publishedOn", description="The timestamp of the publish event"), + ] = None domains: typing.Optional[typing.List[str]] = pydantic.Field(default=None) """ The domains that were published """ published_by: typing_extensions.Annotated[ - typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]], FieldMetadata(alias="publishedBy") - ] = pydantic.Field(default=None) - """ - The name andID of the user who published the site - """ + typing.Optional[typing.Dict[str, typing.Any]], + FieldMetadata(alias="publishedBy"), + pydantic.Field(alias="publishedBy", description="The name andID of the user who published the site"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/sites.py b/src/webflow/types/sites.py index d293ce2..f71410b 100644 --- a/src/webflow/types/sites.py +++ b/src/webflow/types/sites.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .site import Site -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .site import Site class Sites(UniversalBaseModel): diff --git a/src/webflow/types/sku.py b/src/webflow/types/sku.py index 79f159a..f02c4c9 100644 --- a/src/webflow/types/sku.py +++ b/src/webflow/types/sku.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import datetime as dt from .sku_field_data import SkuFieldData -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Sku(UniversalBaseModel): @@ -20,35 +20,29 @@ class Sku(UniversalBaseModel): Unique identifier for the Product """ - cms_locale_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="cmsLocaleId")] = ( - pydantic.Field(default=None) - ) - """ - Identifier for the locale of the CMS item - """ - - last_published: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastPublished")] = ( - pydantic.Field(default=None) - ) - """ - The date the Product was last published - """ - - last_updated: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastUpdated")] = ( - pydantic.Field(default=None) - ) - """ - The date the Product was last updated - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - The date the Product was created - """ - - field_data: typing_extensions.Annotated[typing.Optional[SkuFieldData], FieldMetadata(alias="fieldData")] = None + cms_locale_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="cmsLocaleId"), + pydantic.Field(alias="cmsLocaleId", description="Identifier for the locale of the CMS item"), + ] = None + last_published: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastPublished"), + pydantic.Field(alias="lastPublished", description="The date the Product was last published"), + ] = None + last_updated: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastUpdated"), + pydantic.Field(alias="lastUpdated", description="The date the Product was last updated"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="The date the Product was created"), + ] = None + field_data: typing_extensions.Annotated[ + typing.Optional[SkuFieldData], FieldMetadata(alias="fieldData"), pydantic.Field(alias="fieldData") + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/sku_field_data.py b/src/webflow/types/sku_field_data.py index c7540d8..7cfb6df 100644 --- a/src/webflow/types/sku_field_data.py +++ b/src/webflow/types/sku_field_data.py @@ -1,17 +1,17 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .sku_value_list import SkuValueList -from ..core.serialization import FieldMetadata + import pydantic -from .sku_field_data_price import SkuFieldDataPrice +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .sku_field_data_compare_at_price import SkuFieldDataCompareAtPrice from .sku_field_data_ec_sku_billing_method import SkuFieldDataEcSkuBillingMethod from .sku_field_data_ec_sku_subscription_plan import SkuFieldDataEcSkuSubscriptionPlan +from .sku_field_data_price import SkuFieldDataPrice from .sku_property_list import SkuPropertyList -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .sku_value_list import SkuValueList class SkuFieldData(UniversalBaseModel): @@ -19,7 +19,9 @@ class SkuFieldData(UniversalBaseModel): Standard and Custom fields for a SKU """ - sku_values: typing_extensions.Annotated[typing.Optional[SkuValueList], FieldMetadata(alias="sku-values")] = None + sku_values: typing_extensions.Annotated[ + typing.Optional[SkuValueList], FieldMetadata(alias="sku-values"), pydantic.Field(alias="sku-values") + ] = None name: str = pydantic.Field() """ Name of the Product @@ -36,44 +38,41 @@ class SkuFieldData(UniversalBaseModel): """ compare_at_price: typing_extensions.Annotated[ - typing.Optional[SkuFieldDataCompareAtPrice], FieldMetadata(alias="compare-at-price") - ] = pydantic.Field(default=None) - """ - comparison price of SKU - """ - + typing.Optional[SkuFieldDataCompareAtPrice], + FieldMetadata(alias="compare-at-price"), + pydantic.Field(alias="compare-at-price", description="comparison price of SKU"), + ] = None ec_sku_billing_method: typing_extensions.Annotated[ - typing.Optional[SkuFieldDataEcSkuBillingMethod], FieldMetadata(alias="ec-sku-billing-method") - ] = pydantic.Field(default=None) - """ - [Billing method](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#billing-methods)for the SKU - """ - + typing.Optional[SkuFieldDataEcSkuBillingMethod], + FieldMetadata(alias="ec-sku-billing-method"), + pydantic.Field( + alias="ec-sku-billing-method", + description="[Billing method](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#billing-methods)for the SKU", + ), + ] = None ec_sku_subscription_plan: typing_extensions.Annotated[ - typing.Optional[SkuFieldDataEcSkuSubscriptionPlan], FieldMetadata(alias="ec-sku-subscription-plan") - ] = pydantic.Field(default=None) - """ - [Subscription plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) for the SKU - """ - - main_image: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="main-image")] = pydantic.Field( - default=None - ) - """ - The URL for the main image of the SKU - """ - + typing.Optional[SkuFieldDataEcSkuSubscriptionPlan], + FieldMetadata(alias="ec-sku-subscription-plan"), + pydantic.Field( + alias="ec-sku-subscription-plan", + description="[Subscription plan](https://help.webflow.com/hc/en-us/articles/33961432087955-Add-and-manage-products-and-categories#subscription) for the SKU", + ), + ] = None + main_image: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="main-image"), + pydantic.Field(alias="main-image", description="The URL for the main image of the SKU"), + ] = None sku: typing.Optional[str] = pydantic.Field(default=None) """ A unique identifier for the SKU """ sku_properties: typing_extensions.Annotated[ - typing.Optional[typing.List[SkuPropertyList]], FieldMetadata(alias="sku-properties") - ] = pydantic.Field(default=None) - """ - The properties of the SKU - """ + typing.Optional[typing.List[SkuPropertyList]], + FieldMetadata(alias="sku-properties"), + pydantic.Field(alias="sku-properties", description="The properties of the SKU"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/sku_field_data_compare_at_price.py b/src/webflow/types/sku_field_data_compare_at_price.py index 6b2347f..ba520de 100644 --- a/src/webflow/types/sku_field_data_compare_at_price.py +++ b/src/webflow/types/sku_field_data_compare_at_price.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class SkuFieldDataCompareAtPrice(UniversalBaseModel): diff --git a/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py b/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py index ed2e484..30f60bc 100644 --- a/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py +++ b/src/webflow/types/sku_field_data_ec_sku_subscription_plan.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .sku_field_data_ec_sku_subscription_plan_interval import SkuFieldDataEcSkuSubscriptionPlanInterval + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .sku_field_data_ec_sku_subscription_plan_interval import SkuFieldDataEcSkuSubscriptionPlanInterval from .sku_field_data_ec_sku_subscription_plan_plans_item import SkuFieldDataEcSkuSubscriptionPlanPlansItem -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class SkuFieldDataEcSkuSubscriptionPlan(UniversalBaseModel): diff --git a/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py index 714642e..0b7c397 100644 --- a/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py +++ b/src/webflow/types/sku_field_data_ec_sku_subscription_plan_plans_item.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .sku_field_data_ec_sku_subscription_plan_plans_item_status import SkuFieldDataEcSkuSubscriptionPlanPlansItemStatus -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class SkuFieldDataEcSkuSubscriptionPlanPlansItem(UniversalBaseModel): diff --git a/src/webflow/types/sku_field_data_price.py b/src/webflow/types/sku_field_data_price.py index cb31f4a..17940d7 100644 --- a/src/webflow/types/sku_field_data_price.py +++ b/src/webflow/types/sku_field_data_price.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class SkuFieldDataPrice(UniversalBaseModel): diff --git a/src/webflow/types/sku_property_list.py b/src/webflow/types/sku_property_list.py index f4e0862..3602aa4 100644 --- a/src/webflow/types/sku_property_list.py +++ b/src/webflow/types/sku_property_list.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .sku_property_list_enum_item import SkuPropertyListEnumItem -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class SkuPropertyList(UniversalBaseModel): diff --git a/src/webflow/types/sku_property_list_enum_item.py b/src/webflow/types/sku_property_list_enum_item.py index f35e6d0..2666581 100644 --- a/src/webflow/types/sku_property_list_enum_item.py +++ b/src/webflow/types/sku_property_list_enum_item.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 import typing +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + class SkuPropertyListEnumItem(UniversalBaseModel): """ diff --git a/src/webflow/types/static_field.py b/src/webflow/types/static_field.py index c6e6162..714dc5d 100644 --- a/src/webflow/types/static_field.py +++ b/src/webflow/types/static_field.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .static_field_type import StaticFieldType -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class StaticField(UniversalBaseModel): @@ -15,36 +15,29 @@ class StaticField(UniversalBaseModel): Unique identifier for a Field """ - is_editable: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isEditable")] = pydantic.Field( - default=None - ) - """ - Define whether the field is editable - """ - - is_required: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="isRequired")] = pydantic.Field( - default=None - ) - """ - define whether a field is required in a collection - """ - + is_editable: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isEditable"), + pydantic.Field(alias="isEditable", description="Define whether the field is editable"), + ] = None + is_required: typing_extensions.Annotated[ + typing.Optional[bool], + FieldMetadata(alias="isRequired"), + pydantic.Field(alias="isRequired", description="define whether a field is required in a collection"), + ] = None type: StaticFieldType = pydantic.Field() """ Choose these appropriate field type for your collection data """ - display_name: typing_extensions.Annotated[str, FieldMetadata(alias="displayName")] = pydantic.Field() - """ - The name of a field - """ - - help_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="helpText")] = pydantic.Field( - default=None - ) - """ - Additional text to help anyone filling out this field - """ + display_name: typing_extensions.Annotated[ + str, FieldMetadata(alias="displayName"), pydantic.Field(alias="displayName", description="The name of a field") + ] + help_text: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="helpText"), + pydantic.Field(alias="helpText", description="Additional text to help anyone filling out this field"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/stripe_card.py b/src/webflow/types/stripe_card.py index ccc45ae..55580d9 100644 --- a/src/webflow/types/stripe_card.py +++ b/src/webflow/types/stripe_card.py @@ -1,13 +1,13 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .stripe_card_brand import StripeCardBrand from .stripe_card_expires import StripeCardExpires -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class StripeCard(UniversalBaseModel): @@ -15,25 +15,21 @@ class StripeCard(UniversalBaseModel): Details on the card used to fulfill this order, if this order was finalized with Stripe. """ - last_4: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="last4")] = pydantic.Field( - default=None - ) - """ - The last 4 digits on the card as a string - """ - + last_4: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="last4"), + pydantic.Field(alias="last4", description="The last 4 digits on the card as a string"), + ] = None brand: typing.Optional[StripeCardBrand] = pydantic.Field(default=None) """ The card's brand (ie. credit card network) """ - owner_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="ownerName")] = pydantic.Field( - default=None - ) - """ - The name on the card. - """ - + owner_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="ownerName"), + pydantic.Field(alias="ownerName", description="The name on the card."), + ] = None expires: typing.Optional[StripeCardExpires] = pydantic.Field(default=None) """ The card's expiration date. diff --git a/src/webflow/types/stripe_card_expires.py b/src/webflow/types/stripe_card_expires.py index 3ce14d9..9cf529f 100644 --- a/src/webflow/types/stripe_card_expires.py +++ b/src/webflow/types/stripe_card_expires.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class StripeCardExpires(UniversalBaseModel): diff --git a/src/webflow/types/stripe_details.py b/src/webflow/types/stripe_details.py index 9bd170a..acd103a 100644 --- a/src/webflow/types/stripe_details.py +++ b/src/webflow/types/stripe_details.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata class StripeDetails(UniversalBaseModel): @@ -13,61 +13,48 @@ class StripeDetails(UniversalBaseModel): An object with various Stripe IDs, useful for linking into the stripe dashboard. """ - subscription_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="subscriptionId")] = ( - pydantic.Field(default=None) - ) - """ - Stripe-generated identifier for the Subscription - """ - - payment_method: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="paymentMethod")] = ( - pydantic.Field(default=None) - ) - """ - Stripe-generated identifier for the PaymentMethod used - """ - - payment_intent_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="paymentIntentId")] = ( - pydantic.Field(default=None) - ) - """ - Stripe-generated identifier for the PaymentIntent, or null - """ - - customer_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="customerId")] = pydantic.Field( - default=None - ) - """ - Stripe-generated customer identifier, or null - """ - - charge_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="chargeId")] = pydantic.Field( - default=None - ) - """ - Stripe-generated charge identifier, or null - """ - - dispute_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="disputeId")] = pydantic.Field( - default=None - ) - """ - Stripe-generated dispute identifier, or null - """ - - refund_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="refundId")] = pydantic.Field( - default=None - ) - """ - Stripe-generated refund identifier, or null - """ - - refund_reason: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="refundReason")] = ( - pydantic.Field(default=None) - ) - """ - Stripe-generated refund reason, or null - """ + subscription_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="subscriptionId"), + pydantic.Field(alias="subscriptionId", description="Stripe-generated identifier for the Subscription"), + ] = None + payment_method: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="paymentMethod"), + pydantic.Field(alias="paymentMethod", description="Stripe-generated identifier for the PaymentMethod used"), + ] = None + payment_intent_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="paymentIntentId"), + pydantic.Field( + alias="paymentIntentId", description="Stripe-generated identifier for the PaymentIntent, or null" + ), + ] = None + customer_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="customerId"), + pydantic.Field(alias="customerId", description="Stripe-generated customer identifier, or null"), + ] = None + charge_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="chargeId"), + pydantic.Field(alias="chargeId", description="Stripe-generated charge identifier, or null"), + ] = None + dispute_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="disputeId"), + pydantic.Field(alias="disputeId", description="Stripe-generated dispute identifier, or null"), + ] = None + refund_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="refundId"), + pydantic.Field(alias="refundId", description="Stripe-generated refund identifier, or null"), + ] = None + refund_reason: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="refundReason"), + pydantic.Field(alias="refundReason", description="Stripe-generated refund reason, or null"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/submit_button_node.py b/src/webflow/types/submit_button_node.py index 25ba646..7dc8c94 100644 --- a/src/webflow/types/submit_button_node.py +++ b/src/webflow/types/submit_button_node.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class SubmitButtonNode(UniversalBaseModel): @@ -23,11 +23,11 @@ class SubmitButtonNode(UniversalBaseModel): The text content of the submit button. """ - waiting_text: typing_extensions.Annotated[str, FieldMetadata(alias="waitingText")] = pydantic.Field() - """ - The text to show while the form is submitting. - """ - + waiting_text: typing_extensions.Annotated[ + str, + FieldMetadata(alias="waitingText"), + pydantic.Field(alias="waitingText", description="The text to show while the form is submitting."), + ] attributes: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None) """ The custom attributes of the node diff --git a/src/webflow/types/submit_button_node_write.py b/src/webflow/types/submit_button_node_write.py index 6233215..a3066da 100644 --- a/src/webflow/types/submit_button_node_write.py +++ b/src/webflow/types/submit_button_node_write.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class SubmitButtonNodeWrite(UniversalBaseModel): @@ -13,22 +13,19 @@ class SubmitButtonNodeWrite(UniversalBaseModel): Update a submit button node """ - node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() - """ - Node UUID - """ - + node_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="nodeId"), pydantic.Field(alias="nodeId", description="Node UUID") + ] value: typing.Optional[str] = pydantic.Field(default=None) """ The text content of the submit button. """ - waiting_text: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="waitingText")] = ( - pydantic.Field(default=None) - ) - """ - The text to show while the form is submitting. - """ + waiting_text: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="waitingText"), + pydantic.Field(alias="waitingText", description="The text to show while the form is submitting."), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/text.py b/src/webflow/types/text.py index 913d5d1..337db7c 100644 --- a/src/webflow/types/text.py +++ b/src/webflow/types/text.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class Text(UniversalBaseModel): diff --git a/src/webflow/types/text_input_node.py b/src/webflow/types/text_input_node.py index 7146e15..e884b3c 100644 --- a/src/webflow/types/text_input_node.py +++ b/src/webflow/types/text_input_node.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import pydantic import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class TextInputNode(UniversalBaseModel): diff --git a/src/webflow/types/text_input_node_write.py b/src/webflow/types/text_input_node_write.py index 6ea8e98..12515e9 100644 --- a/src/webflow/types/text_input_node_write.py +++ b/src/webflow/types/text_input_node_write.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import typing class TextInputNodeWrite(UniversalBaseModel): @@ -13,11 +13,9 @@ class TextInputNodeWrite(UniversalBaseModel): Update placeholder text on a text input node """ - node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() - """ - Node UUID - """ - + node_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="nodeId"), pydantic.Field(alias="nodeId", description="Node UUID") + ] placeholder: str = pydantic.Field() """ The placeholder text of the input node diff --git a/src/webflow/types/text_node.py b/src/webflow/types/text_node.py index aa15d4b..c8fea4b 100644 --- a/src/webflow/types/text_node.py +++ b/src/webflow/types/text_node.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from .text_node_text import TextNodeText -import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class TextNode(UniversalBaseModel): diff --git a/src/webflow/types/text_node_text.py b/src/webflow/types/text_node_text.py index 5add2f0..106d502 100644 --- a/src/webflow/types/text_node_text.py +++ b/src/webflow/types/text_node_text.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class TextNodeText(UniversalBaseModel): diff --git a/src/webflow/types/text_node_write.py b/src/webflow/types/text_node_write.py index a16c800..b8ef694 100644 --- a/src/webflow/types/text_node_write.py +++ b/src/webflow/types/text_node_write.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import typing + +import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import typing class TextNodeWrite(UniversalBaseModel): @@ -13,11 +13,9 @@ class TextNodeWrite(UniversalBaseModel): Update a text node """ - node_id: typing_extensions.Annotated[str, FieldMetadata(alias="nodeId")] = pydantic.Field() - """ - Node UUID - """ - + node_id: typing_extensions.Annotated[ + str, FieldMetadata(alias="nodeId"), pydantic.Field(alias="nodeId", description="Node UUID") + ] text: str = pydantic.Field() """ HTML content of the node, including the HTML tag. The HTML tags must be the same as what's returned from the Get Content endpoint. diff --git a/src/webflow/types/updated_order.py b/src/webflow/types/updated_order.py index a3fc241..08d0687 100644 --- a/src/webflow/types/updated_order.py +++ b/src/webflow/types/updated_order.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from ..core.serialization import FieldMetadata + import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata from .order import Order -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class UpdatedOrder(UniversalBaseModel): @@ -14,13 +14,11 @@ class UpdatedOrder(UniversalBaseModel): The Webhook payload for when an order is updated """ - trigger_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="triggerType")] = ( - pydantic.Field(default=None) - ) - """ - The type of event that triggered the request - """ - + trigger_type: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="triggerType"), + pydantic.Field(alias="triggerType", description="The type of event that triggered the request"), + ] = None payload: typing.Optional[Order] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/user_access.py b/src/webflow/types/user_access.py index 7c869dd..0851cd6 100644 --- a/src/webflow/types/user_access.py +++ b/src/webflow/types/user_access.py @@ -1,12 +1,12 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .workspace_audit_log_item_payload_user_access_method import WorkspaceAuditLogItemPayloadUserAccessMethod + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .workspace_audit_log_item_payload_user_access_method import WorkspaceAuditLogItemPayloadUserAccessMethod class UserAccess(UniversalBaseModel): @@ -16,12 +16,11 @@ class UserAccess(UniversalBaseModel): The geolocation based on the logged IP address """ - ip_address: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="ipAddress")] = pydantic.Field( - default=None - ) - """ - The captured IP address of the user - """ + ip_address: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="ipAddress"), + pydantic.Field(alias="ipAddress", description="The captured IP address of the user"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/user_access_audit_log_item.py b/src/webflow/types/user_access_audit_log_item.py index b94e6a7..2d4d877 100644 --- a/src/webflow/types/user_access_audit_log_item.py +++ b/src/webflow/types/user_access_audit_log_item.py @@ -1,18 +1,20 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .user_access import UserAccess -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic +from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType class UserAccessAuditLogItem(UniversalBaseModel): event_sub_type: typing_extensions.Annotated[ - typing.Optional[UserAccessAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + typing.Optional[UserAccessAuditLogItemEventSubType], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[UserAccess] = None diff --git a/src/webflow/types/webhook.py b/src/webflow/types/webhook.py index 226c94f..43f561a 100644 --- a/src/webflow/types/webhook.py +++ b/src/webflow/types/webhook.py @@ -1,14 +1,14 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel +import datetime as dt import typing + import pydantic import typing_extensions -from .trigger_type import TriggerType +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata +from .trigger_type import TriggerType from .webhook_filter import WebhookFilter -import datetime as dt -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class Webhook(UniversalBaseModel): @@ -17,44 +17,41 @@ class Webhook(UniversalBaseModel): Unique identifier for the Webhook registration """ - trigger_type: typing_extensions.Annotated[typing.Optional[TriggerType], FieldMetadata(alias="triggerType")] = None + trigger_type: typing_extensions.Annotated[ + typing.Optional[TriggerType], FieldMetadata(alias="triggerType"), pydantic.Field(alias="triggerType") + ] = None url: typing.Optional[str] = pydantic.Field(default=None) """ URL to send the Webhook payload to """ - workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceId")] = ( - pydantic.Field(default=None) - ) - """ - Unique identifier for the Workspace the Webhook is registered in - """ - - site_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="siteId")] = pydantic.Field( - default=None - ) - """ - Unique identifier for the Site the Webhook is registered in - """ - + workspace_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="workspaceId"), + pydantic.Field( + alias="workspaceId", description="Unique identifier for the Workspace the Webhook is registered in" + ), + ] = None + site_id: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="siteId"), + pydantic.Field(alias="siteId", description="Unique identifier for the Site the Webhook is registered in"), + ] = None filter: typing.Optional[WebhookFilter] = pydantic.Field(default=None) """ Only supported for the `form_submission` trigger type. Filter for the form you want Webhooks to be sent for. """ - last_triggered: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="lastTriggered")] = ( - pydantic.Field(default=None) - ) - """ - Date the Webhook instance was last triggered - """ - - created_on: typing_extensions.Annotated[typing.Optional[dt.datetime], FieldMetadata(alias="createdOn")] = ( - pydantic.Field(default=None) - ) - """ - Date the Webhook registration was created - """ + last_triggered: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="lastTriggered"), + pydantic.Field(alias="lastTriggered", description="Date the Webhook instance was last triggered"), + ] = None + created_on: typing_extensions.Annotated[ + typing.Optional[dt.datetime], + FieldMetadata(alias="createdOn"), + pydantic.Field(alias="createdOn", description="Date the Webhook registration was created"), + ] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/webhook_filter.py b/src/webflow/types/webhook_filter.py index ccffba5..2f47255 100644 --- a/src/webflow/types/webhook_filter.py +++ b/src/webflow/types/webhook_filter.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing + import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class WebhookFilter(UniversalBaseModel): diff --git a/src/webflow/types/webhook_list.py b/src/webflow/types/webhook_list.py index 1740272..6d76207 100644 --- a/src/webflow/types/webhook_list.py +++ b/src/webflow/types/webhook_list.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .webhook import Webhook -from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .pagination import Pagination +from .webhook import Webhook class WebhookList(UniversalBaseModel): diff --git a/src/webflow/types/workspace_audit_log_item.py b/src/webflow/types/workspace_audit_log_item.py index 1936c93..7d3a3c5 100644 --- a/src/webflow/types/workspace_audit_log_item.py +++ b/src/webflow/types/workspace_audit_log_item.py @@ -1,26 +1,27 @@ # This file was auto-generated by Fern from our API Definition. from __future__ import annotations -from ..core.pydantic_utilities import UniversalBaseModel -import typing + import datetime as dt -from .workspace_audit_log_item_actor import WorkspaceAuditLogItemActor -from .workspace_audit_log_item_workspace import WorkspaceAuditLogItemWorkspace -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + import pydantic import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata -from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType -from .user_access import UserAccess -from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType from .custom_role import CustomRole -from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType -from .workspace_membership import WorkspaceMembership -from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType +from .custom_role_audit_log_item_event_sub_type import CustomRoleAuditLogItemEventSubType +from .setting_change import SettingChange from .site_membership import SiteMembership -from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType +from .site_membership_audit_log_item_event_sub_type import SiteMembershipAuditLogItemEventSubType +from .user_access import UserAccess +from .user_access_audit_log_item_event_sub_type import UserAccessAuditLogItemEventSubType +from .workspace_audit_log_item_actor import WorkspaceAuditLogItemActor +from .workspace_audit_log_item_workspace import WorkspaceAuditLogItemWorkspace from .workspace_invitation import WorkspaceInvitation -from .setting_change import SettingChange +from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType +from .workspace_membership import WorkspaceMembership +from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType class Base(UniversalBaseModel): @@ -39,11 +40,13 @@ class Config: class WorkspaceAuditLogItem_UserAccess(Base): - event_type: typing_extensions.Annotated[typing.Literal["user_access"], FieldMetadata(alias="eventType")] = ( - "user_access" - ) + event_type: typing_extensions.Annotated[ + typing.Literal["user_access"], FieldMetadata(alias="eventType"), pydantic.Field(alias="eventType") + ] = "user_access" event_sub_type: typing_extensions.Annotated[ - typing.Optional[UserAccessAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + typing.Optional[UserAccessAuditLogItemEventSubType], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[UserAccess] = None @@ -58,11 +61,13 @@ class Config: class WorkspaceAuditLogItem_CustomRole(Base): - event_type: typing_extensions.Annotated[typing.Literal["custom_role"], FieldMetadata(alias="eventType")] = ( - "custom_role" - ) + event_type: typing_extensions.Annotated[ + typing.Literal["custom_role"], FieldMetadata(alias="eventType"), pydantic.Field(alias="eventType") + ] = "custom_role" event_sub_type: typing_extensions.Annotated[ - typing.Optional[CustomRoleAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + typing.Optional[CustomRoleAuditLogItemEventSubType], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[CustomRole] = None @@ -78,10 +83,12 @@ class Config: class WorkspaceAuditLogItem_WorkspaceMembership(Base): event_type: typing_extensions.Annotated[ - typing.Literal["workspace_membership"], FieldMetadata(alias="eventType") + typing.Literal["workspace_membership"], FieldMetadata(alias="eventType"), pydantic.Field(alias="eventType") ] = "workspace_membership" event_sub_type: typing_extensions.Annotated[ - typing.Optional[WorkspaceMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + typing.Optional[WorkspaceMembershipAuditLogItemEventSubType], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[WorkspaceMembership] = None @@ -96,11 +103,13 @@ class Config: class WorkspaceAuditLogItem_SiteMembership(Base): - event_type: typing_extensions.Annotated[typing.Literal["site_membership"], FieldMetadata(alias="eventType")] = ( - "site_membership" - ) + event_type: typing_extensions.Annotated[ + typing.Literal["site_membership"], FieldMetadata(alias="eventType"), pydantic.Field(alias="eventType") + ] = "site_membership" event_sub_type: typing_extensions.Annotated[ - typing.Optional[SiteMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + typing.Optional[SiteMembershipAuditLogItemEventSubType], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[SiteMembership] = None @@ -116,10 +125,12 @@ class Config: class WorkspaceAuditLogItem_WorkspaceInvitation(Base): event_type: typing_extensions.Annotated[ - typing.Literal["workspace_invitation"], FieldMetadata(alias="eventType") + typing.Literal["workspace_invitation"], FieldMetadata(alias="eventType"), pydantic.Field(alias="eventType") ] = "workspace_invitation" event_sub_type: typing_extensions.Annotated[ - typing.Optional[WorkspaceInvitationAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + typing.Optional[WorkspaceInvitationAuditLogItemEventSubType], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[WorkspaceInvitation] = None @@ -134,11 +145,13 @@ class Config: class WorkspaceAuditLogItem_WorkspaceSetting(Base): - event_type: typing_extensions.Annotated[typing.Literal["workspace_setting"], FieldMetadata(alias="eventType")] = ( - "workspace_setting" - ) + event_type: typing_extensions.Annotated[ + typing.Literal["workspace_setting"], FieldMetadata(alias="eventType"), pydantic.Field(alias="eventType") + ] = "workspace_setting" event_sub_type: typing_extensions.Annotated[ - typing.Optional[typing.Literal["setting_updated"]], FieldMetadata(alias="eventSubType") + typing.Optional[typing.Literal["setting_updated"]], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[SettingChange] = None @@ -152,11 +165,14 @@ class Config: extra = pydantic.Extra.allow -WorkspaceAuditLogItem = typing.Union[ - WorkspaceAuditLogItem_UserAccess, - WorkspaceAuditLogItem_CustomRole, - WorkspaceAuditLogItem_WorkspaceMembership, - WorkspaceAuditLogItem_SiteMembership, - WorkspaceAuditLogItem_WorkspaceInvitation, - WorkspaceAuditLogItem_WorkspaceSetting, +WorkspaceAuditLogItem = typing_extensions.Annotated[ + typing.Union[ + WorkspaceAuditLogItem_UserAccess, + WorkspaceAuditLogItem_CustomRole, + WorkspaceAuditLogItem_WorkspaceMembership, + WorkspaceAuditLogItem_SiteMembership, + WorkspaceAuditLogItem_WorkspaceInvitation, + WorkspaceAuditLogItem_WorkspaceSetting, + ], + pydantic.Field(discriminator="event_type"), ] diff --git a/src/webflow/types/workspace_audit_log_item_actor.py b/src/webflow/types/workspace_audit_log_item_actor.py index 7da609c..ced7149 100644 --- a/src/webflow/types/workspace_audit_log_item_actor.py +++ b/src/webflow/types/workspace_audit_log_item_actor.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class WorkspaceAuditLogItemActor(UniversalBaseModel): diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_granular_access.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_granular_access.py index 8d18539..82f561d 100644 --- a/src/webflow/types/workspace_audit_log_item_payload_site_membership_granular_access.py +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_granular_access.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class WorkspaceAuditLogItemPayloadSiteMembershipGranularAccess(UniversalBaseModel): diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py index 6d392bd..bb6df69 100644 --- a/src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_site.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class WorkspaceAuditLogItemPayloadSiteMembershipSite(UniversalBaseModel): diff --git a/src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py b/src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py index bcfc37b..cf8e343 100644 --- a/src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py +++ b/src/webflow/types/workspace_audit_log_item_payload_site_membership_target_user.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class WorkspaceAuditLogItemPayloadSiteMembershipTargetUser(UniversalBaseModel): diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py index 1360978..9003721 100644 --- a/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_user.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser(UniversalBaseModel): diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_users_item.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_users_item.py index 1338b5f..c18c694 100644 --- a/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_users_item.py +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_invitation_target_users_item.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem(UniversalBaseModel): diff --git a/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py index 6ce0f6a..b2adafa 100644 --- a/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py +++ b/src/webflow/types/workspace_audit_log_item_payload_workspace_membership_target_user.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser(UniversalBaseModel): diff --git a/src/webflow/types/workspace_audit_log_item_workspace.py b/src/webflow/types/workspace_audit_log_item_workspace.py index 6c13bf5..81c18ac 100644 --- a/src/webflow/types/workspace_audit_log_item_workspace.py +++ b/src/webflow/types/workspace_audit_log_item_workspace.py @@ -1,9 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel class WorkspaceAuditLogItemWorkspace(UniversalBaseModel): diff --git a/src/webflow/types/workspace_audit_log_response.py b/src/webflow/types/workspace_audit_log_response.py index f6d0d13..e31a69e 100644 --- a/src/webflow/types/workspace_audit_log_response.py +++ b/src/webflow/types/workspace_audit_log_response.py @@ -1,11 +1,11 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel import typing -from .workspace_audit_log_item import WorkspaceAuditLogItem -from .pagination import Pagination -from ..core.pydantic_utilities import IS_PYDANTIC_V2 + import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .pagination import Pagination +from .workspace_audit_log_item import WorkspaceAuditLogItem class WorkspaceAuditLogResponse(UniversalBaseModel): diff --git a/src/webflow/types/workspace_invitation.py b/src/webflow/types/workspace_invitation.py index a096af1..a8a99f5 100644 --- a/src/webflow/types/workspace_invitation.py +++ b/src/webflow/types/workspace_invitation.py @@ -1,50 +1,51 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .workspace_audit_log_item_payload_workspace_invitation_target_user import ( - WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, -) + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .workspace_audit_log_item_payload_workspace_invitation_method import ( WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod, ) -from .workspace_audit_log_item_payload_workspace_invitation_user_type import ( - WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, +from .workspace_audit_log_item_payload_workspace_invitation_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser, ) -import pydantic from .workspace_audit_log_item_payload_workspace_invitation_target_users_item import ( WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem, ) -from ..core.pydantic_utilities import IS_PYDANTIC_V2 +from .workspace_audit_log_item_payload_workspace_invitation_user_type import ( + WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType, +) class WorkspaceInvitation(UniversalBaseModel): target_user: typing_extensions.Annotated[ - typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser], FieldMetadata(alias="targetUser") + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUser], + FieldMetadata(alias="targetUser"), + pydantic.Field(alias="targetUser"), ] = None method: typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceInvitationMethod] = None user_type: typing_extensions.Annotated[ - typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType], FieldMetadata(alias="userType") + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceInvitationUserType], + FieldMetadata(alias="userType"), + pydantic.Field(alias="userType"), + ] = None + role_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="roleName"), + pydantic.Field(alias="roleName", description="The name of the role that was assigned to the user"), + ] = None + previous_role_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="previousRoleName"), + pydantic.Field(alias="previousRoleName", description="The previous role that the user had"), ] = None - role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( - default=None - ) - """ - The name of the role that was assigned to the user - """ - - previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( - pydantic.Field(default=None) - ) - """ - The previous role that the user had - """ - target_users: typing_extensions.Annotated[ typing.Optional[typing.List[WorkspaceAuditLogItemPayloadWorkspaceInvitationTargetUsersItem]], FieldMetadata(alias="targetUsers"), + pydantic.Field(alias="targetUsers"), ] = None if IS_PYDANTIC_V2: diff --git a/src/webflow/types/workspace_invitation_audit_log_item.py b/src/webflow/types/workspace_invitation_audit_log_item.py index e41f504..7b57c27 100644 --- a/src/webflow/types/workspace_invitation_audit_log_item.py +++ b/src/webflow/types/workspace_invitation_audit_log_item.py @@ -1,18 +1,20 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .workspace_invitation import WorkspaceInvitation -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic +from .workspace_invitation_audit_log_item_event_sub_type import WorkspaceInvitationAuditLogItemEventSubType class WorkspaceInvitationAuditLogItem(UniversalBaseModel): event_sub_type: typing_extensions.Annotated[ - typing.Optional[WorkspaceInvitationAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + typing.Optional[WorkspaceInvitationAuditLogItemEventSubType], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[WorkspaceInvitation] = None diff --git a/src/webflow/types/workspace_membership.py b/src/webflow/types/workspace_membership.py index 1c369a2..b5996f7 100644 --- a/src/webflow/types/workspace_membership.py +++ b/src/webflow/types/workspace_membership.py @@ -1,43 +1,44 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .workspace_audit_log_item_payload_workspace_membership_target_user import ( - WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, -) + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .workspace_audit_log_item_payload_workspace_membership_method import ( WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod, ) +from .workspace_audit_log_item_payload_workspace_membership_target_user import ( + WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser, +) from .workspace_audit_log_item_payload_workspace_membership_user_type import ( WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType, ) -import pydantic -from ..core.pydantic_utilities import IS_PYDANTIC_V2 class WorkspaceMembership(UniversalBaseModel): target_user: typing_extensions.Annotated[ - typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser], FieldMetadata(alias="targetUser") + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceMembershipTargetUser], + FieldMetadata(alias="targetUser"), + pydantic.Field(alias="targetUser"), ] = None method: typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceMembershipMethod] = None user_type: typing_extensions.Annotated[ - typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType], FieldMetadata(alias="userType") + typing.Optional[WorkspaceAuditLogItemPayloadWorkspaceMembershipUserType], + FieldMetadata(alias="userType"), + pydantic.Field(alias="userType"), + ] = None + role_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="roleName"), + pydantic.Field(alias="roleName", description="The name of the role that was assigned to the user"), + ] = None + previous_role_name: typing_extensions.Annotated[ + typing.Optional[str], + FieldMetadata(alias="previousRoleName"), + pydantic.Field(alias="previousRoleName", description="The previous role that the user had"), ] = None - role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="roleName")] = pydantic.Field( - default=None - ) - """ - The name of the role that was assigned to the user - """ - - previous_role_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="previousRoleName")] = ( - pydantic.Field(default=None) - ) - """ - The previous role that the user had - """ if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/webflow/types/workspace_membership_audit_log_item.py b/src/webflow/types/workspace_membership_audit_log_item.py index 4ac92d7..20dab22 100644 --- a/src/webflow/types/workspace_membership_audit_log_item.py +++ b/src/webflow/types/workspace_membership_audit_log_item.py @@ -1,18 +1,20 @@ # This file was auto-generated by Fern from our API Definition. -from ..core.pydantic_utilities import UniversalBaseModel -import typing_extensions import typing -from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel from ..core.serialization import FieldMetadata from .workspace_membership import WorkspaceMembership -from ..core.pydantic_utilities import IS_PYDANTIC_V2 -import pydantic +from .workspace_membership_audit_log_item_event_sub_type import WorkspaceMembershipAuditLogItemEventSubType class WorkspaceMembershipAuditLogItem(UniversalBaseModel): event_sub_type: typing_extensions.Annotated[ - typing.Optional[WorkspaceMembershipAuditLogItemEventSubType], FieldMetadata(alias="eventSubType") + typing.Optional[WorkspaceMembershipAuditLogItemEventSubType], + FieldMetadata(alias="eventSubType"), + pydantic.Field(alias="eventSubType"), ] = None payload: typing.Optional[WorkspaceMembership] = None diff --git a/tests/collections/__init__.py b/tests/collections/__init__.py deleted file mode 100644 index f3ea265..0000000 --- a/tests/collections/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/tests/collections/test_fields.py b/tests/collections/test_fields.py deleted file mode 100644 index dc18ff3..0000000 --- a/tests/collections/test_fields.py +++ /dev/null @@ -1,106 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from webflow import StaticField -from ..utilities import validate_response - - -async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "562ac0395358780a1f5e6fbc", - "isEditable": True, - "isRequired": False, - "type": "RichText", - "displayName": "Post Body", - "helpText": "Add the body of your post here", - } - expected_types: typing.Any = { - "id": None, - "isEditable": None, - "isRequired": None, - "type": None, - "displayName": None, - "helpText": None, - } - response = client.collections.fields.create( - collection_id="580e63fc8c9a982ac9b8b745", - request=StaticField( - id="562ac0395358780a1f5e6fbc", - is_editable=True, - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", - ), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.fields.create( - collection_id="580e63fc8c9a982ac9b8b745", - request=StaticField( - id="562ac0395358780a1f5e6fbc", - is_editable=True, - is_required=False, - type="RichText", - display_name="Post Body", - help_text="Add the body of your post here", - ), - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.collections.fields.delete(collection_id="580e63fc8c9a982ac9b8b745", field_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.collections.fields.delete( - collection_id="580e63fc8c9a982ac9b8b745", field_id="580e63fc8c9a982ac9b8b745" - ) # type: ignore[func-returns-value] - is None - ) - - -async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "75821f618da60c18383330bcc0ca488b", - "isRequired": False, - "isEditable": True, - "type": "RichText", - "slug": "post-body", - "displayName": "Post Body", - "helpText": "Add the body of your post here", - "validations": {"additionalProperties": "additionalProperties"}, - } - expected_types: typing.Any = { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - "validations": {"additionalProperties": None}, - } - response = client.collections.fields.update( - collection_id="580e63fc8c9a982ac9b8b745", - field_id="580e63fc8c9a982ac9b8b745", - is_required=False, - display_name="Post Body", - help_text="Add the body of your post here", - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.fields.update( - collection_id="580e63fc8c9a982ac9b8b745", - field_id="580e63fc8c9a982ac9b8b745", - is_required=False, - display_name="Post Body", - help_text="Add the body of your post here", - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/collections/test_items.py b/tests/collections/test_items.py deleted file mode 100644 index 0b0807c..0000000 --- a/tests/collections/test_items.py +++ /dev/null @@ -1,1068 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from ..utilities import validate_response -from webflow import CollectionItemPostSingle -from webflow import CollectionItemPostSingleFieldData -from webflow.resources.collections.resources.items import ItemsDeleteItemsRequestItemsItem -from webflow import CollectionItemWithIdInput -from webflow import CollectionItemWithIdInputFieldData -from webflow import CollectionItem -from webflow import CollectionItemFieldData -from webflow.resources.collections.resources.items import ItemsDeleteItemsLiveRequestItemsItem -from webflow.resources.collections.resources.items import SingleCmsItem -from webflow import CollectionItemPatchSingleFieldData -from webflow.resources.collections.resources.items import ItemIDs - - -async def test_list_items(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "items": [ - { - "id": "62b720ef280c7a7a3be8cabe", - "cmsLocaleId": "66f6e966c9e1dc700a857ca3", - "lastPublished": "2022-06-30T13:35:20.878Z", - "lastUpdated": "2022-06-25T14:51:27.809Z", - "createdOn": "2022-06-25T14:51:27.809Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "Senior Data Analyst", - "slug": "senior-data-analyst", - "url": "https://boards.greenhouse.io/webflow/jobs/26567701", - "department": "Data", - }, - }, - { - "id": "62c880ef281c7b7b4cf9dabc", - "cmsLocaleId": "66f6e966c9e1dc700a857ca3", - "lastPublished": "2023-04-15T10:25:18.123Z", - "lastUpdated": "2023-04-10T11:45:30.567Z", - "createdOn": "2023-04-10T11:45:30.567Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "Product Manager", - "slug": "product-manager", - "url": "https://boards.greenhouse.io/webflow/jobs/31234567", - "department": "Product", - }, - }, - ], - "pagination": {"limit": 25, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "items": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - 1: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.collections.items.list_items( - collection_id="580e63fc8c9a982ac9b8b745", - cms_locale_id="cmsLocaleId", - offset=1, - limit=1, - name="name", - slug="slug", - sort_by="lastPublished", - sort_order="asc", - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.list_items( - collection_id="580e63fc8c9a982ac9b8b745", - cms_locale_id="cmsLocaleId", - offset=1, - limit=1, - name="name", - slug="slug", - sort_by="lastPublished", - sort_order="asc", - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_create_item(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "42b720ef280c7a7a3be8cabe", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2022-11-29T16:22:43.159Z", - "lastUpdated": "2022-11-17T17:19:43.282Z", - "createdOn": "2022-11-17T17:11:57.148Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "The Hitchhiker's Guide to the Galaxy", - "slug": "hitchhikers-guide-to-the-galaxy", - "plain-text": "Don't Panic.", - "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", - "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - "image-gallery": [ - {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, - {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - ], - "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", - "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", - "contact-email": "zaphod.beeblebrox@heartofgold.gov", - "support-phone": "424-242-4242", - "answer-to-everything": 42, - "release-date": "1979-10-12T00:00:00.000Z", - "is-featured": True, - "brand-color": "#000000", - "category": "62b720ef280c7a7a3be8cabf", - "author": "62b720ef280c7a7a3be8cab0", - "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], - "downloadable-asset": { - "fileId": "62b720ef280c7a7a3be8cab3", - "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", - }, - }, - } - expected_types: typing.Any = { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - } - response = client.collections.items.create_item( - collection_id="580e63fc8c9a982ac9b8b745", - skip_invalid_files=True, - request=CollectionItemPostSingle( - is_archived=False, - is_draft=False, - field_data=CollectionItemPostSingleFieldData( - name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" - ), - ), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.create_item( - collection_id="580e63fc8c9a982ac9b8b745", - skip_invalid_files=True, - request=CollectionItemPostSingle( - is_archived=False, - is_draft=False, - field_data=CollectionItemPostSingleFieldData( - name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" - ), - ), - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_delete_items(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.collections.items.delete_items( - collection_id="580e63fc8c9a982ac9b8b745", - items=[ItemsDeleteItemsRequestItemsItem(id="580e64008c9a982ac9b8b754")], - ) # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.collections.items.delete_items( - collection_id="580e63fc8c9a982ac9b8b745", - items=[ItemsDeleteItemsRequestItemsItem(id="580e64008c9a982ac9b8b754")], - ) # type: ignore[func-returns-value] - is None - ) - - -async def test_update_items(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "items": [ - { - "id": "66f6ed9576ddacf3149d5ea6", - "cmsLocaleId": "66f6e966c9e1dc700a857ca5", - "lastPublished": "2024-09-27T17:38:29.066Z", - "lastUpdated": "2024-09-27T17:38:29.066Z", - "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": False, - "isDraft": False, - "fieldData": {"name": "Ne Paniquez Pas", "slug": "ne-paniquez-pas", "featured": False}, - }, - { - "id": "66f6ed9576ddacf3149d5ea6", - "cmsLocaleId": "66f6e966c9e1dc700a857ca4", - "lastPublished": "2024-09-27T17:38:29.066Z", - "lastUpdated": "2024-09-27T17:38:29.066Z", - "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": False, - "isDraft": False, - "fieldData": {"name": "No Entrar en Pánico", "slug": "no-entrar-en-panico", "featured": False}, - }, - { - "id": "66f6ed9576ddacf3149d5eaa", - "cmsLocaleId": "66f6e966c9e1dc700a857ca5", - "lastPublished": "2024-09-27T17:38:29.066Z", - "lastUpdated": "2024-09-27T17:38:29.066Z", - "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "Au Revoir et Merci pour Tous les Poissons", - "slug": "au-revoir-et-merci", - "featured": False, - }, - }, - { - "id": "66f6ed9576ddacf3149d5eaa", - "cmsLocaleId": "66f6e966c9e1dc700a857ca4", - "lastPublished": "2024-09-27T17:38:29.066Z", - "lastUpdated": "2024-09-27T17:38:29.066Z", - "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "Hasta Luego y Gracias por Todo el Pescado", - "slug": "hasta-luego-y-gracias", - "featured": False, - }, - }, - ], - "pagination": {"limit": 25, "offset": 0, "total": 4}, - } - expected_types: typing.Any = { - "items": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - 1: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - 2: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - 3: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.collections.items.update_items( - collection_id="580e63fc8c9a982ac9b8b745", - skip_invalid_files=True, - items=[ - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5ea6", - cms_locale_id="66f6e966c9e1dc700a857ca5", - field_data=CollectionItemWithIdInputFieldData(name="Ne Paniquez Pas", slug="ne-paniquez-pas"), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5ea6", - cms_locale_id="66f6e966c9e1dc700a857ca4", - field_data=CollectionItemWithIdInputFieldData(name="No Entrar en Pánico", slug="no-entrar-en-panico"), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5eaa", - cms_locale_id="66f6e966c9e1dc700a857ca5", - field_data=CollectionItemWithIdInputFieldData( - name="Au Revoir et Merci pour Tous les Poissons", slug="au-revoir-et-merci" - ), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5eaa", - cms_locale_id="66f6e966c9e1dc700a857ca4", - field_data=CollectionItemWithIdInputFieldData( - name="Hasta Luego y Gracias por Todo el Pescado", slug="hasta-luego-y-gracias" - ), - ), - ], - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.update_items( - collection_id="580e63fc8c9a982ac9b8b745", - skip_invalid_files=True, - items=[ - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5ea6", - cms_locale_id="66f6e966c9e1dc700a857ca5", - field_data=CollectionItemWithIdInputFieldData(name="Ne Paniquez Pas", slug="ne-paniquez-pas"), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5ea6", - cms_locale_id="66f6e966c9e1dc700a857ca4", - field_data=CollectionItemWithIdInputFieldData(name="No Entrar en Pánico", slug="no-entrar-en-panico"), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5eaa", - cms_locale_id="66f6e966c9e1dc700a857ca5", - field_data=CollectionItemWithIdInputFieldData( - name="Au Revoir et Merci pour Tous les Poissons", slug="au-revoir-et-merci" - ), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5eaa", - cms_locale_id="66f6e966c9e1dc700a857ca4", - field_data=CollectionItemWithIdInputFieldData( - name="Hasta Luego y Gracias por Todo el Pescado", slug="hasta-luego-y-gracias" - ), - ), - ], - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_list_items_live(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "items": [ - { - "id": "62b720ef280c7a7a3be8cabe", - "cmsLocaleId": "66f6e966c9e1dc700a857ca3", - "lastPublished": "2022-06-30T13:35:20.878Z", - "lastUpdated": "2022-06-25T14:51:27.809Z", - "createdOn": "2022-06-25T14:51:27.809Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "Senior Data Analyst", - "slug": "senior-data-analyst", - "url": "https://boards.greenhouse.io/webflow/jobs/26567701", - "department": "Data", - }, - }, - { - "id": "62c880ef281c7b7b4cf9dabc", - "cmsLocaleId": "66f6e966c9e1dc700a857ca3", - "lastPublished": "2023-04-15T10:25:18.123Z", - "lastUpdated": "2023-04-10T11:45:30.567Z", - "createdOn": "2023-04-10T11:45:30.567Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "Product Manager", - "slug": "product-manager", - "url": "https://boards.greenhouse.io/webflow/jobs/31234567", - "department": "Product", - }, - }, - ], - "pagination": {"limit": 25, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "items": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - 1: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.collections.items.list_items_live( - collection_id="580e63fc8c9a982ac9b8b745", - cms_locale_id="cmsLocaleId", - offset=1, - limit=1, - name="name", - slug="slug", - sort_by="lastPublished", - sort_order="asc", - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.list_items_live( - collection_id="580e63fc8c9a982ac9b8b745", - cms_locale_id="cmsLocaleId", - offset=1, - limit=1, - name="name", - slug="slug", - sort_by="lastPublished", - sort_order="asc", - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_create_item_live(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "42b720ef280c7a7a3be8cabe", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2022-11-29T16:22:43.159Z", - "lastUpdated": "2022-11-17T17:19:43.282Z", - "createdOn": "2022-11-17T17:11:57.148Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "The Hitchhiker's Guide to the Galaxy", - "slug": "hitchhikers-guide-to-the-galaxy", - "plain-text": "Don't Panic.", - "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", - "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - "image-gallery": [ - {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, - {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - ], - "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", - "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", - "contact-email": "zaphod.beeblebrox@heartofgold.gov", - "support-phone": "424-242-4242", - "answer-to-everything": 42, - "release-date": "1979-10-12T00:00:00.000Z", - "is-featured": True, - "brand-color": "#000000", - "category": "62b720ef280c7a7a3be8cabf", - "author": "62b720ef280c7a7a3be8cab0", - "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], - "downloadable-asset": { - "fileId": "62b720ef280c7a7a3be8cab3", - "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", - }, - }, - } - expected_types: typing.Any = { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - } - response = client.collections.items.create_item_live( - collection_id="580e63fc8c9a982ac9b8b745", - skip_invalid_files=True, - request=CollectionItem( - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" - ), - ), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.create_item_live( - collection_id="580e63fc8c9a982ac9b8b745", - skip_invalid_files=True, - request=CollectionItem( - is_archived=False, - is_draft=False, - field_data=CollectionItemFieldData( - name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" - ), - ), - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_delete_items_live(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.collections.items.delete_items_live( - collection_id="580e63fc8c9a982ac9b8b745", - items=[ItemsDeleteItemsLiveRequestItemsItem(id="580e64008c9a982ac9b8b754")], - ) # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.collections.items.delete_items_live( - collection_id="580e63fc8c9a982ac9b8b745", - items=[ItemsDeleteItemsLiveRequestItemsItem(id="580e64008c9a982ac9b8b754")], - ) # type: ignore[func-returns-value] - is None - ) - - -async def test_update_items_live(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "items": [ - { - "id": "66f6ed9576ddacf3149d5ea6", - "cmsLocaleId": "66f6e966c9e1dc700a857ca5", - "lastPublished": "2024-09-27T17:38:29.066Z", - "lastUpdated": "2024-09-27T17:38:29.066Z", - "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": False, - "isDraft": False, - "fieldData": {"name": "Ne Paniquez Pas", "slug": "ne-paniquez-pas", "featured": False}, - }, - { - "id": "66f6ed9576ddacf3149d5ea6", - "cmsLocaleId": "66f6e966c9e1dc700a857ca4", - "lastPublished": "2024-09-27T17:38:29.066Z", - "lastUpdated": "2024-09-27T17:38:29.066Z", - "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": False, - "isDraft": False, - "fieldData": {"name": "No Entrar en Pánico", "slug": "no-entrar-en-panico", "featured": False}, - }, - { - "id": "66f6ed9576ddacf3149d5eaa", - "cmsLocaleId": "66f6e966c9e1dc700a857ca5", - "lastPublished": "2024-09-27T17:38:29.066Z", - "lastUpdated": "2024-09-27T17:38:29.066Z", - "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "Au Revoir et Merci pour Tous les Poissons", - "slug": "au-revoir-et-merci", - "featured": False, - }, - }, - { - "id": "66f6ed9576ddacf3149d5eaa", - "cmsLocaleId": "66f6e966c9e1dc700a857ca4", - "lastPublished": "2024-09-27T17:38:29.066Z", - "lastUpdated": "2024-09-27T17:38:29.066Z", - "createdOn": "2024-09-27T17:38:29.066Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "Hasta Luego y Gracias por Todo el Pescado", - "slug": "hasta-luego-y-gracias", - "featured": False, - }, - }, - ] - } - expected_types: typing.Any = { - "items": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - 1: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - 2: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - 3: { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - }, - }, - ) - } - response = client.collections.items.update_items_live( - collection_id="580e63fc8c9a982ac9b8b745", - skip_invalid_files=True, - items=[ - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5ea6", - cms_locale_id="66f6e966c9e1dc700a857ca5", - field_data=CollectionItemWithIdInputFieldData(name="Ne Paniquez Pas", slug="ne-paniquez-pas"), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5ea6", - cms_locale_id="66f6e966c9e1dc700a857ca4", - field_data=CollectionItemWithIdInputFieldData(name="No Entrar en Pánico", slug="no-entrar-en-panico"), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5eaa", - cms_locale_id="66f6e966c9e1dc700a857ca5", - field_data=CollectionItemWithIdInputFieldData( - name="Au Revoir et Merci pour Tous les Poissons", slug="au-revoir-et-merci" - ), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5eaa", - cms_locale_id="66f6e966c9e1dc700a857ca4", - field_data=CollectionItemWithIdInputFieldData( - name="Hasta Luego y Gracias por Todo el Pescado", slug="hasta-luego-y-gracias" - ), - ), - ], - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.update_items_live( - collection_id="580e63fc8c9a982ac9b8b745", - skip_invalid_files=True, - items=[ - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5ea6", - cms_locale_id="66f6e966c9e1dc700a857ca5", - field_data=CollectionItemWithIdInputFieldData(name="Ne Paniquez Pas", slug="ne-paniquez-pas"), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5ea6", - cms_locale_id="66f6e966c9e1dc700a857ca4", - field_data=CollectionItemWithIdInputFieldData(name="No Entrar en Pánico", slug="no-entrar-en-panico"), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5eaa", - cms_locale_id="66f6e966c9e1dc700a857ca5", - field_data=CollectionItemWithIdInputFieldData( - name="Au Revoir et Merci pour Tous les Poissons", slug="au-revoir-et-merci" - ), - ), - CollectionItemWithIdInput( - id="66f6ed9576ddacf3149d5eaa", - cms_locale_id="66f6e966c9e1dc700a857ca4", - field_data=CollectionItemWithIdInputFieldData( - name="Hasta Luego y Gracias por Todo el Pescado", slug="hasta-luego-y-gracias" - ), - ), - ], - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_create_items(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "580e64008c9a982ac9b8b754", - "cmsLocaleIds": ["653ad57de882f528b32e810e", "6514390aea353fc691d69827", "65143930ea353fc691d69cd8"], - "lastPublished": "2023-03-17T18:47:35.560Z", - "lastUpdated": "2023-03-17T18:47:35.560Z", - "createdOn": "2023-03-17T18:47:35.560Z", - "isArchived": True, - "isDraft": True, - "fieldData": { - "name": "My new item", - "slug": "my-new-item", - "date": "2022-11-18T00:00:00.000Z", - "featured": False, - "color": "#db4b68", - }, - } - expected_types: typing.Any = { - "id": None, - "cmsLocaleIds": ("list", {0: None, 1: None, 2: None}), - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - } - response = client.collections.items.create_items( - collection_id="580e63fc8c9a982ac9b8b745", - skip_invalid_files=True, - cms_locale_ids=["66f6e966c9e1dc700a857ca3", "66f6e966c9e1dc700a857ca4", "66f6e966c9e1dc700a857ca5"], - is_archived=False, - is_draft=False, - field_data=SingleCmsItem(name="Don’t Panic", slug="dont-panic"), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.create_items( - collection_id="580e63fc8c9a982ac9b8b745", - skip_invalid_files=True, - cms_locale_ids=["66f6e966c9e1dc700a857ca3", "66f6e966c9e1dc700a857ca4", "66f6e966c9e1dc700a857ca5"], - is_archived=False, - is_draft=False, - field_data=SingleCmsItem(name="Don’t Panic", slug="dont-panic"), - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get_item(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "42b720ef280c7a7a3be8cabe", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2022-11-29T16:22:43.159Z", - "lastUpdated": "2022-11-17T17:19:43.282Z", - "createdOn": "2022-11-17T17:11:57.148Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "The Hitchhiker's Guide to the Galaxy", - "slug": "hitchhikers-guide-to-the-galaxy", - "plain-text": "Don't Panic.", - "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", - "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - "image-gallery": [ - {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, - {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - ], - "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", - "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", - "contact-email": "zaphod.beeblebrox@heartofgold.gov", - "support-phone": "424-242-4242", - "answer-to-everything": 42, - "release-date": "1979-10-12T00:00:00.000Z", - "is-featured": True, - "brand-color": "#000000", - "category": "62b720ef280c7a7a3be8cabf", - "author": "62b720ef280c7a7a3be8cab0", - "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], - "downloadable-asset": { - "fileId": "62b720ef280c7a7a3be8cab3", - "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", - }, - }, - } - expected_types: typing.Any = { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - } - response = client.collections.items.get_item( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.get_item( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_delete_item(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.collections.items.delete_item( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" - ) # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.collections.items.delete_item( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" - ) # type: ignore[func-returns-value] - is None - ) - - -async def test_update_item(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "42b720ef280c7a7a3be8cabe", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2022-11-29T16:22:43.159Z", - "lastUpdated": "2022-11-17T17:19:43.282Z", - "createdOn": "2022-11-17T17:11:57.148Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "The Hitchhiker's Guide to the Galaxy", - "slug": "hitchhikers-guide-to-the-galaxy", - "plain-text": "Don't Panic.", - "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", - "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - "image-gallery": [ - {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, - {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - ], - "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", - "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", - "contact-email": "zaphod.beeblebrox@heartofgold.gov", - "support-phone": "424-242-4242", - "answer-to-everything": 42, - "release-date": "1979-10-12T00:00:00.000Z", - "is-featured": True, - "brand-color": "#000000", - "category": "62b720ef280c7a7a3be8cabf", - "author": "62b720ef280c7a7a3be8cab0", - "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], - "downloadable-asset": { - "fileId": "62b720ef280c7a7a3be8cab3", - "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", - }, - }, - } - expected_types: typing.Any = { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - } - response = client.collections.items.update_item( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", - skip_invalid_files=True, - is_archived=False, - is_draft=False, - field_data=CollectionItemPatchSingleFieldData( - name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" - ), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.update_item( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", - skip_invalid_files=True, - is_archived=False, - is_draft=False, - field_data=CollectionItemPatchSingleFieldData( - name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" - ), - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get_item_live(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "42b720ef280c7a7a3be8cabe", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2022-11-29T16:22:43.159Z", - "lastUpdated": "2022-11-17T17:19:43.282Z", - "createdOn": "2022-11-17T17:11:57.148Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "The Hitchhiker's Guide to the Galaxy", - "slug": "hitchhikers-guide-to-the-galaxy", - "plain-text": "Don't Panic.", - "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", - "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - "image-gallery": [ - {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, - {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - ], - "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", - "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", - "contact-email": "zaphod.beeblebrox@heartofgold.gov", - "support-phone": "424-242-4242", - "answer-to-everything": 42, - "release-date": "1979-10-12T00:00:00.000Z", - "is-featured": True, - "brand-color": "#000000", - "category": "62b720ef280c7a7a3be8cabf", - "author": "62b720ef280c7a7a3be8cab0", - "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], - "downloadable-asset": { - "fileId": "62b720ef280c7a7a3be8cab3", - "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", - }, - }, - } - expected_types: typing.Any = { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - } - response = client.collections.items.get_item_live( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.get_item_live( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_delete_item_live(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.collections.items.delete_item_live( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" - ) # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.collections.items.delete_item_live( - collection_id="580e63fc8c9a982ac9b8b745", item_id="580e64008c9a982ac9b8b754", cms_locale_id="cmsLocaleId" - ) # type: ignore[func-returns-value] - is None - ) - - -async def test_update_item_live(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "42b720ef280c7a7a3be8cabe", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2022-11-29T16:22:43.159Z", - "lastUpdated": "2022-11-17T17:19:43.282Z", - "createdOn": "2022-11-17T17:11:57.148Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "The Hitchhiker's Guide to the Galaxy", - "slug": "hitchhikers-guide-to-the-galaxy", - "plain-text": "Don't Panic.", - "rich-text": "

A Guide to Interstellar Travel

A towel is about the most massively useful thing an interstellar hitchhiker can have. Don't forget yours!

", - "main-image": {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - "image-gallery": [ - {"fileId": "62b720ef280c7a7a3be8cabd", "url": "/files/62b720ef280c7a7a3be8cabd_image.png"}, - {"fileId": "62b720ef280c7a7a3be8cabe", "url": "/files/62b720ef280c7a7a3be8cabe_image.png"}, - ], - "intro-video": "https://www.youtube.com/watch?v=aJ83KAggd-4", - "official-site": "https://hitchhikers.fandom.com/wiki/The_Hitchhiker%27s_Guide_to_the_Galaxy", - "contact-email": "zaphod.beeblebrox@heartofgold.gov", - "support-phone": "424-242-4242", - "answer-to-everything": 42, - "release-date": "1979-10-12T00:00:00.000Z", - "is-featured": True, - "brand-color": "#000000", - "category": "62b720ef280c7a7a3be8cabf", - "author": "62b720ef280c7a7a3be8cab0", - "tags": ["62b720ef280c7a7a3be8cab1", "62b720ef280c7a7a3be8cab2"], - "downloadable-asset": { - "fileId": "62b720ef280c7a7a3be8cab3", - "url": "/files/62b720ef280c7a7a3be8cab3_document.pdf", - }, - }, - } - expected_types: typing.Any = { - "id": None, - "cmsLocaleId": None, - "lastPublished": None, - "lastUpdated": None, - "createdOn": None, - "isArchived": None, - "isDraft": None, - "fieldData": {"name": None, "slug": None}, - } - response = client.collections.items.update_item_live( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", - skip_invalid_files=True, - is_archived=False, - is_draft=False, - field_data=CollectionItemPatchSingleFieldData( - name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" - ), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.update_item_live( - collection_id="580e63fc8c9a982ac9b8b745", - item_id="580e64008c9a982ac9b8b754", - skip_invalid_files=True, - is_archived=False, - is_draft=False, - field_data=CollectionItemPatchSingleFieldData( - name="The Hitchhiker's Guide to the Galaxy", slug="hitchhikers-guide-to-the-galaxy" - ), - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_publish_item(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "publishedItemIds": ["643fd856d66b6528195ee2ca", "643fd856d66b6528195ee2cb"], - "errors": ["Staging item ID 643fd856d66b6528195ee2cf not found."], - } - expected_types: typing.Any = {"publishedItemIds": ("list", {0: None, 1: None}), "errors": ("list", {0: None})} - response = client.collections.items.publish_item( - collection_id="580e63fc8c9a982ac9b8b745", - request=ItemIDs(item_ids=["643fd856d66b6528195ee2ca", "643fd856d66b6528195ee2cb", "643fd856d66b6528195ee2cc"]), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.items.publish_item( - collection_id="580e63fc8c9a982ac9b8b745", - request=ItemIDs(item_ids=["643fd856d66b6528195ee2ca", "643fd856d66b6528195ee2cb", "643fd856d66b6528195ee2cc"]), - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index 398d344..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,31 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -import os -from webflow.environment import WebflowEnvironment -import pytest -from webflow import AsyncWebflow - - -@pytest.fixture -def client() -> Webflow: - return Webflow( - access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), - environment=WebflowEnvironment( - base=os.getenv("TESTS_BASE_URL", "base_url"), - data_api=os.getenv("TESTS_BASE_URL", "base_url"), - content_delivery_api=os.getenv("TESTS_BASE_URL", "base_url"), - ), - ) - - -@pytest.fixture -def async_client() -> AsyncWebflow: - return AsyncWebflow( - access_token=os.getenv("ENV_ACCESS_TOKEN", "access_token"), - environment=WebflowEnvironment( - base=os.getenv("TESTS_BASE_URL", "base_url"), - data_api=os.getenv("TESTS_BASE_URL", "base_url"), - content_delivery_api=os.getenv("TESTS_BASE_URL", "base_url"), - ), - ) diff --git a/tests/custom/test_client.py b/tests/custom/test_client.py index 73f811f..ab04ce6 100644 --- a/tests/custom/test_client.py +++ b/tests/custom/test_client.py @@ -4,4 +4,4 @@ # Get started with writing tests with pytest at https://docs.pytest.org @pytest.mark.skip(reason="Unimplemented") def test_client() -> None: - assert True == True + assert True diff --git a/tests/pages/__init__.py b/tests/pages/__init__.py deleted file mode 100644 index f3ea265..0000000 --- a/tests/pages/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/tests/pages/test_scripts.py b/tests/pages/test_scripts.py deleted file mode 100644 index 0e553d2..0000000 --- a/tests/pages/test_scripts.py +++ /dev/null @@ -1,85 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from ..utilities import validate_response -from webflow import ScriptApply - - -async def test_get_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "scripts": [{"id": "id", "location": "header", "version": "version", "attributes": {"key": "value"}}], - "lastUpdated": "lastUpdated", - "createdOn": "createdOn", - } - expected_types: typing.Any = { - "scripts": ( - "list", - {0: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}}, - ), - "lastUpdated": None, - "createdOn": None, - } - response = client.pages.scripts.get_custom_code(page_id="63c720f9347c2139b248e552") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.pages.scripts.get_custom_code(page_id="63c720f9347c2139b248e552") - validate_response(async_response, expected_response, expected_types) - - -async def test_upsert_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "scripts": [ - { - "id": "cms_slider", - "location": "header", - "version": "1.0.0", - "attributes": {"my-attribute": "some-value"}, - }, - {"id": "alert", "location": "header", "version": "0.0.1", "attributes": {"key": "value"}}, - ], - "lastUpdated": "2022-10-26T00:28:54.191Z", - "createdOn": "2022-10-26T00:28:54.191Z", - } - expected_types: typing.Any = { - "scripts": ( - "list", - { - 0: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, - 1: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, - }, - ), - "lastUpdated": None, - "createdOn": None, - } - response = client.pages.scripts.upsert_custom_code( - page_id="63c720f9347c2139b248e552", - scripts=[ - ScriptApply(id="cms_slider", location="header", version="1.0.0", attributes={"my-attribute": "some-value"}), - ScriptApply(id="alert", location="header", version="0.0.1"), - ], - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.pages.scripts.upsert_custom_code( - page_id="63c720f9347c2139b248e552", - scripts=[ - ScriptApply(id="cms_slider", location="header", version="1.0.0", attributes={"my-attribute": "some-value"}), - ScriptApply(id="alert", location="header", version="0.0.1"), - ], - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_delete_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.pages.scripts.delete_custom_code(page_id="63c720f9347c2139b248e552") # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.pages.scripts.delete_custom_code(page_id="63c720f9347c2139b248e552") # type: ignore[func-returns-value] - is None - ) diff --git a/tests/sites/__init__.py b/tests/sites/__init__.py deleted file mode 100644 index f3ea265..0000000 --- a/tests/sites/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/tests/sites/test_activity_logs.py b/tests/sites/test_activity_logs.py deleted file mode 100644 index 5046daa..0000000 --- a/tests/sites/test_activity_logs.py +++ /dev/null @@ -1,53 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from ..utilities import validate_response - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "items": [ - { - "id": "654c16c7b229e56bcf26872d", - "createdOn": "2023-11-08T23:16:23Z", - "lastUpdated": "2023-11-08T23:16:23Z", - "event": "cms_collection", - "resourceOperation": "CREATED", - "user": {"id": "6509cd56e90eec668b009712", "displayName": "John Doe"}, - "resourceId": "654c16c7b229e56bcf26870c", - "resourceName": "foo-bar", - "newValue": "newValue", - "previousValue": "previousValue", - "payload": {"key": "value"}, - } - ], - "pagination": {"limit": 25, "offset": 0, "total": 1}, - } - expected_types: typing.Any = { - "items": ( - "list", - { - 0: { - "id": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - "event": None, - "resourceOperation": None, - "user": {"id": None, "displayName": None}, - "resourceId": None, - "resourceName": None, - "newValue": None, - "previousValue": None, - "payload": ("dict", {0: (None, None)}), - } - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.sites.activity_logs.list(site_id="580e63e98c9a982ac9b8b741", limit=1, offset=1) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.activity_logs.list(site_id="580e63e98c9a982ac9b8b741", limit=1, offset=1) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_comments.py b/tests/sites/test_comments.py deleted file mode 100644 index a8a81b6..0000000 --- a/tests/sites/test_comments.py +++ /dev/null @@ -1,242 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from ..utilities import validate_response - - -async def test_list_comment_threads(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "comments": [ - { - "id": "679d2ddb5196117ad04d1ffa", - "siteId": "679826b3b20b045e176bc4b5", - "pageId": "679826b3b20b045e176bc4bc", - "localeId": "67993753d910db250db64b3e", - "itemId": "580e64008c9a982ac9b8b754", - "breakpoint": "main", - "url": "https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc", - "content": "Let's go to the pub! [[6287ec36a841b25637c663df]] ", - "isResolved": False, - "author": { - "userId": "6287ec36a841b25637c663df", - "email": "ford.prefect@heartofgold.spaceship", - "name": "Ford Prefect", - }, - "mentionedUsers": [ - { - "userId": "6287ec36a841b25637c663df", - "email": "arthur.dent@heartofgold.spaceship", - "name": "Arthur Dent", - } - ], - "createdOn": "2025-01-31T20:08:59.759Z", - "lastUpdated": "2025-01-31T20:08:59.759Z", - }, - { - "id": "679d2ddb5196117ad04d1ffc", - "siteId": "679826b3b20b045e176bc4b5", - "pageId": "679826b3b20b045e176bc4bc", - "localeId": "67993753d910db250db64b3e", - "itemId": "580e64008c9a982ac9b8b754", - "breakpoint": "main", - "url": "https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc", - "content": "You have five minutes left to drink it [[6287ec36a841b25637c663df]] ", - "isResolved": False, - "author": { - "userId": "6287ec36a841b25637c663df", - "email": "ford.prefect@heartofgold.spaceship", - "name": "Ford Prefect", - }, - "mentionedUsers": [ - { - "userId": "6287ec36a841b25637c663df", - "email": "arthur.dent@heartofgold.spaceship", - "name": "Arthur Dent", - } - ], - "createdOn": "2025-01-31T20:08:59.759Z", - "lastUpdated": "2025-01-31T20:08:59.759Z", - }, - ], - "pagination": {"limit": 2, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "comments": ( - "list", - { - 0: { - "id": None, - "siteId": None, - "pageId": None, - "localeId": None, - "itemId": None, - "breakpoint": None, - "url": None, - "content": None, - "isResolved": None, - "author": {"userId": None, "email": None, "name": None}, - "mentionedUsers": ("list", {0: {"userId": None, "email": None, "name": None}}), - "createdOn": None, - "lastUpdated": None, - }, - 1: { - "id": None, - "siteId": None, - "pageId": None, - "localeId": None, - "itemId": None, - "breakpoint": None, - "url": None, - "content": None, - "isResolved": None, - "author": {"userId": None, "email": None, "name": None}, - "mentionedUsers": ("list", {0: {"userId": None, "email": None, "name": None}}), - "createdOn": None, - "lastUpdated": None, - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.sites.comments.list_comment_threads( - site_id="580e63e98c9a982ac9b8b741", - locale_id="65427cf400e02b306eaa04a0", - offset=1, - limit=1, - sort_by="createdOn", - sort_order="asc", - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.comments.list_comment_threads( - site_id="580e63e98c9a982ac9b8b741", - locale_id="65427cf400e02b306eaa04a0", - offset=1, - limit=1, - sort_by="createdOn", - sort_order="asc", - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get_comment_thread(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "580e64008c9a982ac9b8b754", - "siteId": "580e64008c9a982ac9b8b754", - "pageId": "580e64008c9a982ac9b8b754", - "localeId": "580e64008c9a982ac9b8b754", - "itemId": "580e64008c9a982ac9b8b754", - "breakpoint": "main", - "url": "https://webflow.com/design/site-slug-4ec832?workflow=comment&commentId=679d2ddb5196117ad04d1ff8&pageId=679826b3b20b045e176bc4bc", - "content": "This is a comment reply", - "isResolved": True, - "author": {"userId": "userId", "email": "email", "name": "name"}, - "mentionedUsers": [ - {"userId": "6287ec36a841b25637c663df", "email": "arthur.dent@heartofgold.spaceship", "name": "Arthur Dent"} - ], - "createdOn": "2023-03-17T18:47:35.560Z", - "lastUpdated": "2023-03-17T18:47:35.560Z", - } - expected_types: typing.Any = { - "id": None, - "siteId": None, - "pageId": None, - "localeId": None, - "itemId": None, - "breakpoint": None, - "url": None, - "content": None, - "isResolved": None, - "author": {"userId": None, "email": None, "name": None}, - "mentionedUsers": ("list", {0: {"userId": None, "email": None, "name": None}}), - "createdOn": None, - "lastUpdated": None, - } - response = client.sites.comments.get_comment_thread( - site_id="580e63e98c9a982ac9b8b741", - comment_thread_id="580e63e98c9a982ac9b8b741", - locale_id="65427cf400e02b306eaa04a0", - offset=1, - limit=1, - sort_by="createdOn", - sort_order="asc", - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.comments.get_comment_thread( - site_id="580e63e98c9a982ac9b8b741", - comment_thread_id="580e63e98c9a982ac9b8b741", - locale_id="65427cf400e02b306eaa04a0", - offset=1, - limit=1, - sort_by="createdOn", - sort_order="asc", - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_list_comment_replies(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "comments": [ - { - "id": "679d2ddb5196117ad04d1ffa", - "commentId": "679d2ddb5196117ad04d1ff8", - "siteId": "679826b3b20b045e176bc4b5", - "pageId": "679826b3b20b045e176bc4bc", - "localeId": "67993753d910db250db64b3e", - "breakpoint": "main", - "content": "This comment mentions another user [[6287ec36a841b25637c663df]] ", - "isResolved": False, - "author": {"id": "id", "email": "email", "name": "name"}, - "mentionedUsers": [{"id": "id", "email": "arthur.dent@example.com", "name": "Arthur Dent"}], - "lastUpdated": "2025-01-31T20:08:59.759Z", - "createdOn": "2025-01-31T20:08:59.759Z", - } - ], - "pagination": {"limit": 2, "offset": 0, "total": 1}, - } - expected_types: typing.Any = { - "comments": ( - "list", - { - 0: { - "id": None, - "commentId": None, - "siteId": None, - "pageId": None, - "localeId": None, - "breakpoint": None, - "content": None, - "isResolved": None, - "author": {"id": None, "email": None, "name": None}, - "mentionedUsers": ("list", {0: {"id": None, "email": None, "name": None}}), - "lastUpdated": None, - "createdOn": None, - } - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.sites.comments.list_comment_replies( - site_id="580e63e98c9a982ac9b8b741", - comment_thread_id="580e63e98c9a982ac9b8b741", - locale_id="65427cf400e02b306eaa04a0", - offset=1, - limit=1, - sort_by="createdOn", - sort_order="asc", - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.comments.list_comment_replies( - site_id="580e63e98c9a982ac9b8b741", - comment_thread_id="580e63e98c9a982ac9b8b741", - locale_id="65427cf400e02b306eaa04a0", - offset=1, - limit=1, - sort_by="createdOn", - sort_order="asc", - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_forms.py b/tests/sites/test_forms.py deleted file mode 100644 index bb8b724..0000000 --- a/tests/sites/test_forms.py +++ /dev/null @@ -1,193 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from ..utilities import validate_response - - -async def test_list_submissions_by_site(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "formSubmissions": [ - { - "id": "6321ca84df3949bfc6752327", - "displayName": "Sample Form", - "siteId": "62749158efef318abc8d5a0f", - "workspaceId": "62749158efef318abc8d5a0f", - "dateSubmitted": "2022-09-14T12:35:16Z", - "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, - }, - { - "id": "660d64fabf6e0a0d4edab981", - "displayName": "Sample Form", - "siteId": "62749158efef318abc8d5a0f", - "workspaceId": "62749158efef318abc8d5a0f", - "dateSubmitted": "2022-09-14T12:35:16Z", - "formResponse": {"First Name": "Ford", "Last Name": "Prefect"}, - }, - ], - "pagination": {"limit": 25, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "formSubmissions": ( - "list", - { - 0: { - "id": None, - "displayName": None, - "siteId": None, - "workspaceId": None, - "dateSubmitted": "datetime", - "formResponse": ("dict", {0: (None, None), 1: (None, None)}), - }, - 1: { - "id": None, - "displayName": None, - "siteId": None, - "workspaceId": None, - "dateSubmitted": "datetime", - "formResponse": ("dict", {0: (None, None), 1: (None, None)}), - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.sites.forms.list_submissions_by_site( - site_id="580e63e98c9a982ac9b8b741", element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0", offset=1, limit=1 - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.forms.list_submissions_by_site( - site_id="580e63e98c9a982ac9b8b741", element_id="18259716-3e5a-646a-5f41-5dc4b9405aa0", offset=1, limit=1 - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_list_submissions(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "formSubmissions": [ - { - "id": "6321ca84df3949bfc6752327", - "displayName": "Sample Form", - "siteId": "62749158efef318abc8d5a0f", - "workspaceId": "62749158efef318abc8d5a0f", - "dateSubmitted": "2022-09-14T12:35:16Z", - "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, - }, - { - "id": "660d64fabf6e0a0d4edab981", - "displayName": "Sample Form", - "siteId": "62749158efef318abc8d5a0f", - "workspaceId": "62749158efef318abc8d5a0f", - "dateSubmitted": "2022-09-14T12:35:16Z", - "formResponse": {"First Name": "Ford", "Last Name": "Prefect"}, - }, - ], - "pagination": {"limit": 25, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "formSubmissions": ( - "list", - { - 0: { - "id": None, - "displayName": None, - "siteId": None, - "workspaceId": None, - "dateSubmitted": "datetime", - "formResponse": ("dict", {0: (None, None), 1: (None, None)}), - }, - 1: { - "id": None, - "displayName": None, - "siteId": None, - "workspaceId": None, - "dateSubmitted": "datetime", - "formResponse": ("dict", {0: (None, None), 1: (None, None)}), - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.sites.forms.list_submissions( - site_id="580e63e98c9a982ac9b8b741", form_id="580e63e98c9a982ac9b8b741", offset=1, limit=1 - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.forms.list_submissions( - site_id="580e63e98c9a982ac9b8b741", form_id="580e63e98c9a982ac9b8b741", offset=1, limit=1 - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get_submission(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "6321ca84df3949bfc6752327", - "displayName": "Sample Form", - "siteId": "62749158efef318abc8d5a0f", - "workspaceId": "62749158efef318abc8d5a0f", - "dateSubmitted": "2022-09-14T12:35:16Z", - "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, - } - expected_types: typing.Any = { - "id": None, - "displayName": None, - "siteId": None, - "workspaceId": None, - "dateSubmitted": "datetime", - "formResponse": ("dict", {0: (None, None), 1: (None, None)}), - } - response = client.sites.forms.get_submission( - site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.forms.get_submission( - site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_delete_submission(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.sites.forms.delete_submission( - site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" - ) # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.sites.forms.delete_submission( - site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" - ) # type: ignore[func-returns-value] - is None - ) - - -async def test_update_submission(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "6321ca84df3949bfc6752327", - "displayName": "Sample Form", - "siteId": "62749158efef318abc8d5a0f", - "workspaceId": "62749158efef318abc8d5a0f", - "dateSubmitted": "2022-09-14T12:35:16Z", - "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, - } - expected_types: typing.Any = { - "id": None, - "displayName": None, - "siteId": None, - "workspaceId": None, - "dateSubmitted": "datetime", - "formResponse": ("dict", {0: (None, None), 1: (None, None)}), - } - response = client.sites.forms.update_submission( - site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.forms.update_submission( - site_id="580e63e98c9a982ac9b8b741", form_submission_id="580e63e98c9a982ac9b8b741" - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_plans.py b/tests/sites/test_plans.py deleted file mode 100644 index 01c304e..0000000 --- a/tests/sites/test_plans.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from ..utilities import validate_response - - -async def test_get_site_plan(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "hosting-business-v4", - "name": "Business Hosting", - "pricingInfo": "https://webflow.com/pricing", - } - expected_types: typing.Any = {"id": None, "name": None, "pricingInfo": None} - response = client.sites.plans.get_site_plan(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.plans.get_site_plan(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_redirects.py b/tests/sites/test_redirects.py deleted file mode 100644 index 59b7a48..0000000 --- a/tests/sites/test_redirects.py +++ /dev/null @@ -1,88 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from ..utilities import validate_response - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "redirects": [ - {"id": "42e1a2b7aa1a13f768a0042a", "fromUrl": "/mostly-harmless", "toUrl": "/earth"}, - {"id": "6x9e7f8d9a4b1c2d3e4f5678", "fromUrl": "/babel-fish", "toUrl": "/translate"}, - ], - "pagination": {"limit": 100, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "redirects": ( - "list", - {0: {"id": None, "fromUrl": None, "toUrl": None}, 1: {"id": None, "fromUrl": None, "toUrl": None}}, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.sites.redirects.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.redirects.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = {"id": "42e1a2b7aa1a13f768a0042a", "fromUrl": "/mostly-harmless", "toUrl": "/earth"} - expected_types: typing.Any = {"id": None, "fromUrl": None, "toUrl": None} - response = client.sites.redirects.create( - site_id="580e63e98c9a982ac9b8b741", id="42e1a2b7aa1a13f768a0042a", from_url="/mostly-harmless", to_url="/earth" - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.redirects.create( - site_id="580e63e98c9a982ac9b8b741", id="42e1a2b7aa1a13f768a0042a", from_url="/mostly-harmless", to_url="/earth" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "redirects": [ - {"id": "42e1a2b7aa1a13f768a0042a", "fromUrl": "/mostly-harmless", "toUrl": "/earth"}, - {"id": "6x9e7f8d9a4b1c2d3e4f5678", "fromUrl": "/babel-fish", "toUrl": "/translate"}, - ], - "pagination": {"limit": 100, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "redirects": ( - "list", - {0: {"id": None, "fromUrl": None, "toUrl": None}, 1: {"id": None, "fromUrl": None, "toUrl": None}}, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.sites.redirects.delete(site_id="580e63e98c9a982ac9b8b741", redirect_id="66c4cb9a20cac35ed19500e6") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.redirects.delete( - site_id="580e63e98c9a982ac9b8b741", redirect_id="66c4cb9a20cac35ed19500e6" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = {"id": "42e1a2b7aa1a13f768a0042a", "fromUrl": "/mostly-harmless", "toUrl": "/earth"} - expected_types: typing.Any = {"id": None, "fromUrl": None, "toUrl": None} - response = client.sites.redirects.update( - site_id="580e63e98c9a982ac9b8b741", - redirect_id="66c4cb9a20cac35ed19500e6", - id="42e1a2b7aa1a13f768a0042a", - from_url="/mostly-harmless", - to_url="/earth", - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.redirects.update( - site_id="580e63e98c9a982ac9b8b741", - redirect_id="66c4cb9a20cac35ed19500e6", - id="42e1a2b7aa1a13f768a0042a", - from_url="/mostly-harmless", - to_url="/earth", - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_robots_txt.py b/tests/sites/test_robots_txt.py deleted file mode 100644 index cb38204..0000000 --- a/tests/sites/test_robots_txt.py +++ /dev/null @@ -1,145 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from ..utilities import validate_response -from webflow import RobotsRulesItem - - -async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "rules": [ - { - "userAgent": "googlebot", - "allows": ["/public"], - "disallows": ["/vogon-poetry", "/total-perspective-vortex"], - } - ], - "sitemap": "https://heartofgold.ship/sitemap.xml", - } - expected_types: typing.Any = { - "rules": ( - "list", - {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, - ), - "sitemap": None, - } - response = client.sites.robots_txt.get(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.robots_txt.get(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_put(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "rules": [ - { - "userAgent": "googlebot", - "allows": ["/public"], - "disallows": ["/vogon-poetry", "/total-perspective-vortex"], - } - ], - "sitemap": "https://heartofgold.ship/sitemap.xml", - } - expected_types: typing.Any = { - "rules": ( - "list", - {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, - ), - "sitemap": None, - } - response = client.sites.robots_txt.put( - site_id="580e63e98c9a982ac9b8b741", - rules=[ - RobotsRulesItem( - user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] - ) - ], - sitemap="https://heartofgold.ship/sitemap.xml", - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.robots_txt.put( - site_id="580e63e98c9a982ac9b8b741", - rules=[ - RobotsRulesItem( - user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] - ) - ], - sitemap="https://heartofgold.ship/sitemap.xml", - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "rules": [ - { - "userAgent": "googlebot", - "allows": ["/public"], - "disallows": ["/vogon-poetry", "/total-perspective-vortex"], - } - ], - "sitemap": "https://heartofgold.ship/sitemap.xml", - } - expected_types: typing.Any = { - "rules": ( - "list", - {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, - ), - "sitemap": None, - } - response = client.sites.robots_txt.delete( - site_id="580e63e98c9a982ac9b8b741", - rules=[RobotsRulesItem(user_agent="*", allows=["/public"], disallows=["/bubbles"])], - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.robots_txt.delete( - site_id="580e63e98c9a982ac9b8b741", - rules=[RobotsRulesItem(user_agent="*", allows=["/public"], disallows=["/bubbles"])], - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_patch(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "rules": [ - { - "userAgent": "googlebot", - "allows": ["/public"], - "disallows": ["/vogon-poetry", "/total-perspective-vortex"], - } - ], - "sitemap": "https://heartofgold.ship/sitemap.xml", - } - expected_types: typing.Any = { - "rules": ( - "list", - {0: {"userAgent": None, "allows": ("list", {0: None}), "disallows": ("list", {0: None, 1: None})}}, - ), - "sitemap": None, - } - response = client.sites.robots_txt.patch( - site_id="580e63e98c9a982ac9b8b741", - rules=[ - RobotsRulesItem( - user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] - ) - ], - sitemap="https://heartofgold.ship/sitemap.xml", - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.robots_txt.patch( - site_id="580e63e98c9a982ac9b8b741", - rules=[ - RobotsRulesItem( - user_agent="googlebot", allows=["/public"], disallows=["/vogon-poetry", "/total-perspective-vortex"] - ) - ], - sitemap="https://heartofgold.ship/sitemap.xml", - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_scripts.py b/tests/sites/test_scripts.py deleted file mode 100644 index 47c5179..0000000 --- a/tests/sites/test_scripts.py +++ /dev/null @@ -1,156 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from ..utilities import validate_response -from webflow import ScriptApply - - -async def test_get_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "scripts": [ - { - "id": "cms_slider", - "location": "header", - "version": "1.0.0", - "attributes": {"my-attribute": "some-value"}, - }, - {"id": "alert", "location": "header", "version": "0.0.1", "attributes": {"key": "value"}}, - ], - "lastUpdated": "2022-10-26T00:28:54.191Z", - "createdOn": "2022-10-26T00:28:54.191Z", - } - expected_types: typing.Any = { - "scripts": ( - "list", - { - 0: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, - 1: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, - }, - ), - "lastUpdated": None, - "createdOn": None, - } - response = client.sites.scripts.get_custom_code(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.scripts.get_custom_code(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_upsert_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "scripts": [ - { - "id": "cms_slider", - "location": "header", - "version": "1.0.0", - "attributes": {"my-attribute": "some-value"}, - }, - {"id": "alert", "location": "header", "version": "0.0.1", "attributes": {"key": "value"}}, - ], - "lastUpdated": "lastUpdated", - "createdOn": "createdOn", - } - expected_types: typing.Any = { - "scripts": ( - "list", - { - 0: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, - 1: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}, - }, - ), - "lastUpdated": None, - "createdOn": None, - } - response = client.sites.scripts.upsert_custom_code( - site_id="580e63e98c9a982ac9b8b741", - scripts=[ - ScriptApply(id="cms_slider", location="header", version="1.0.0", attributes={"my-attribute": "some-value"}), - ScriptApply(id="alert", location="header", version="0.0.1"), - ], - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.scripts.upsert_custom_code( - site_id="580e63e98c9a982ac9b8b741", - scripts=[ - ScriptApply(id="cms_slider", location="header", version="1.0.0", attributes={"my-attribute": "some-value"}), - ScriptApply(id="alert", location="header", version="0.0.1"), - ], - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_delete_custom_code(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.sites.scripts.delete_custom_code(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.sites.scripts.delete_custom_code(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] - is None - ) - - -async def test_list_custom_code_blocks(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "blocks": [ - { - "siteId": "6258612d1ee792848f805dcf", - "pageId": "pageId", - "type": "site", - "scripts": [ - {"id": "chartjs", "location": "header", "version": "4.4.2", "attributes": {"key": "value"}} - ], - "createdOn": "2024-04-03T16:49:15Z", - "lastUpdated": "2024-04-03T16:49:15Z", - }, - { - "siteId": "6390c49674a71f84b51a08d8", - "pageId": "6419db964a9c43f6a3af6348", - "type": "page", - "scripts": [{"id": "id", "location": "header", "version": "version"}], - "createdOn": "2022-10-26T00:28:54Z", - "lastUpdated": "2022-10-26T00:28:54Z", - }, - ], - "pagination": {"limit": 10, "offset": 0, "total": 1}, - } - expected_types: typing.Any = { - "blocks": ( - "list", - { - 0: { - "siteId": None, - "pageId": None, - "type": None, - "scripts": ( - "list", - {0: {"id": None, "location": None, "version": None, "attributes": ("dict", {0: (None, None)})}}, - ), - "createdOn": "datetime", - "lastUpdated": "datetime", - }, - 1: { - "siteId": None, - "pageId": None, - "type": None, - "scripts": ("list", {0: {"id": None, "location": None, "version": None}}), - "createdOn": "datetime", - "lastUpdated": "datetime", - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.sites.scripts.list_custom_code_blocks(site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.scripts.list_custom_code_blocks( - site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1 - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/sites/test_well_known.py b/tests/sites/test_well_known.py deleted file mode 100644 index ad81052..0000000 --- a/tests/sites/test_well_known.py +++ /dev/null @@ -1,40 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow - - -async def test_put(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.sites.well_known.put( - site_id="580e63e98c9a982ac9b8b741", - file_name="apple-app-site-association.txt", - file_data='{\n "applinks": {\n "apps": [],\n "details": [\n {\n "appID": "ABCDE12345.com.example.app",\n "paths": [ "/*", "/some/path/*" ]\n }\n ]\n }\n}\n', - content_type="application/json", - ) # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.sites.well_known.put( - site_id="580e63e98c9a982ac9b8b741", - file_name="apple-app-site-association.txt", - file_data='{\n "applinks": {\n "apps": [],\n "details": [\n {\n "appID": "ABCDE12345.com.example.app",\n "paths": [ "/*", "/some/path/*" ]\n }\n ]\n }\n}\n', - content_type="application/json", - ) # type: ignore[func-returns-value] - is None - ) - - -async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.sites.well_known.delete(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.sites.well_known.delete(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] - is None - ) diff --git a/tests/test_assets.py b/tests/test_assets.py deleted file mode 100644 index 3ae051d..0000000 --- a/tests/test_assets.py +++ /dev/null @@ -1,409 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "assets": [ - { - "id": "63e5889e7fe4eafa7384cea4", - "contentType": "image/png", - "size": 2212772, - "siteId": "63938b302ea6b0aa6f3d8745", - "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg", - "originalFileName": "Candy-Wrapper.svg", - "displayName": "63e5889e7fe4eafa7384cea4_Candy-Wrapper.png", - "lastUpdated": "2023-03-01T23:42:57Z", - "createdOn": "2023-02-09T23:58:22Z", - "variants": [ - { - "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "originalFileName": "Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "displayName": "660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "format": "png", - "width": 500, - "height": 900, - "quality": 100, - } - ], - "altText": "A single candy wrapper", - }, - { - "id": "63e5889e7fe4eafa7384cea5", - "contentType": "image/png", - "size": 2212772, - "siteId": "63938b302ea6b0aa6f3d8745", - "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg", - "originalFileName": "Gum-Wrapper.svg", - "displayName": "63e5889e7fe4eafa7384cea5_Gum-Wrapper.png", - "lastUpdated": "2023-03-01T23:42:57Z", - "createdOn": "2023-02-09T23:58:22Z", - "variants": [ - { - "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "originalFileName": "Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "displayName": "660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "format": "png", - "width": 500, - "height": 900, - "quality": 100, - } - ], - "altText": "A single gum wrapper", - }, - ], - "pagination": {"limit": 2, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "assets": ( - "list", - { - 0: { - "id": None, - "contentType": None, - "size": "integer", - "siteId": None, - "hostedUrl": None, - "originalFileName": None, - "displayName": None, - "lastUpdated": "datetime", - "createdOn": "datetime", - "variants": ( - "list", - { - 0: { - "hostedUrl": None, - "originalFileName": None, - "displayName": None, - "format": None, - "width": "integer", - "height": "integer", - "quality": "integer", - } - }, - ), - "altText": None, - }, - 1: { - "id": None, - "contentType": None, - "size": "integer", - "siteId": None, - "hostedUrl": None, - "originalFileName": None, - "displayName": None, - "lastUpdated": "datetime", - "createdOn": "datetime", - "variants": ( - "list", - { - 0: { - "hostedUrl": None, - "originalFileName": None, - "displayName": None, - "format": None, - "width": "integer", - "height": "integer", - "quality": "integer", - } - }, - ), - "altText": None, - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.assets.list(site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.assets.list(site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) - validate_response(async_response, expected_response, expected_types) - - -async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "uploadDetails": { - "acl": "public-read", - "bucket": "webflow-bucket-name", - "X-Amz-Algorithm": "AWS4-HMAC-SHA256", - "X-Amz-Credential": "///s3/aws4_request", - "X-Amz-Date": "", - "key": "/_", - "Policy": "", - "X-Amz-Signature": "", - "success_action_status": "201", - "content-type": "image/png", - "Cache-Control": "max-age=31536000, must-revalidate", - }, - "contentType": "image/png", - "id": "64358b9544249dc43d37d2b7", - "parentFolder": "6436b1ce5281cace05b65aea", - "uploadUrl": "https://s3.amazonaws.com/webflow-dev-assets/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png", - "assetUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d907ab9e91e3e9f56385e_paranoidAndroid-2024.png", - "hostedUrl": "https://dev-assets.website-files.com/643021114e290e0d3a0602b2/64358b9544249dc43d37d2b7_Screenshot%202023-04-11%20at%209.50.42%20AM.png", - "originalFileName": "file.png", - "createdOn": "2023-04-11T16:32:21Z", - "lastUpdated": "2023-04-12T20:31:03Z", - } - expected_types: typing.Any = { - "uploadDetails": { - "acl": None, - "bucket": None, - "X-Amz-Algorithm": None, - "X-Amz-Credential": None, - "X-Amz-Date": None, - "key": None, - "Policy": None, - "X-Amz-Signature": None, - "success_action_status": None, - "content-type": None, - "Cache-Control": None, - }, - "contentType": None, - "id": None, - "parentFolder": None, - "uploadUrl": None, - "assetUrl": None, - "hostedUrl": None, - "originalFileName": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - } - response = client.assets.create( - site_id="580e63e98c9a982ac9b8b741", file_name="file.png", file_hash="3c7d87c9575702bc3b1e991f4d3c638e" - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.assets.create( - site_id="580e63e98c9a982ac9b8b741", file_name="file.png", file_hash="3c7d87c9575702bc3b1e991f4d3c638e" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "63e5889e7fe4eafa7384cea4", - "contentType": "image/png", - "size": 2212772, - "siteId": "63938b302ea6b0aa6f3d8745", - "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg", - "originalFileName": "Candy-Wrapper.svg", - "displayName": "63e5889e7fe4eafa7384cea4_Candy-Wrapper.png", - "lastUpdated": "2023-03-01T23:42:57Z", - "createdOn": "2023-02-09T23:58:22Z", - "variants": [ - { - "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "originalFileName": "Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "displayName": "660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "format": "png", - "width": 500, - "height": 900, - "quality": 100, - "error": "error", - } - ], - "altText": "A single candy wrapper", - } - expected_types: typing.Any = { - "id": None, - "contentType": None, - "size": "integer", - "siteId": None, - "hostedUrl": None, - "originalFileName": None, - "displayName": None, - "lastUpdated": "datetime", - "createdOn": "datetime", - "variants": ( - "list", - { - 0: { - "hostedUrl": None, - "originalFileName": None, - "displayName": None, - "format": None, - "width": "integer", - "height": "integer", - "quality": "integer", - "error": None, - } - }, - ), - "altText": None, - } - response = client.assets.get(asset_id="580e63fc8c9a982ac9b8b745") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.assets.get(asset_id="580e63fc8c9a982ac9b8b745") - validate_response(async_response, expected_response, expected_types) - - -async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.assets.delete(asset_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.assets.delete(asset_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] - is None - ) - - -async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "63e5889e7fe4eafa7384cea4", - "contentType": "image/png", - "size": 2212772, - "siteId": "63938b302ea6b0aa6f3d8745", - "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/63938b302ea6b0aa6f3d8745/63e5889e7fe4eafa7384cea4_Vectors-Wrapper.svg", - "originalFileName": "Candy-Wrapper.svg", - "displayName": "63e5889e7fe4eafa7384cea4_Candy-Wrapper.png", - "lastUpdated": "2023-03-01T23:42:57Z", - "createdOn": "2023-02-09T23:58:22Z", - "variants": [ - { - "hostedUrl": "https://s3.amazonaws.com/webflow-prod-assets/6258612d1ee792848f805dcf/660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "originalFileName": "Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "displayName": "660d83ce30f3a599ddb0bdb3_Screenshot%202024-03-20%20at%209.03.24%E2%80%AFPM-p-500.png", - "format": "png", - "width": 500, - "height": 900, - "quality": 100, - "error": "error", - } - ], - "altText": "A single candy wrapper", - } - expected_types: typing.Any = { - "id": None, - "contentType": None, - "size": "integer", - "siteId": None, - "hostedUrl": None, - "originalFileName": None, - "displayName": None, - "lastUpdated": "datetime", - "createdOn": "datetime", - "variants": ( - "list", - { - 0: { - "hostedUrl": None, - "originalFileName": None, - "displayName": None, - "format": None, - "width": "integer", - "height": "integer", - "quality": "integer", - "error": None, - } - }, - ), - "altText": None, - } - response = client.assets.update(asset_id="580e63fc8c9a982ac9b8b745") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.assets.update(asset_id="580e63fc8c9a982ac9b8b745") - validate_response(async_response, expected_response, expected_types) - - -async def test_list_folders(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "assetFolders": [ - { - "id": "6390c49774a71f0e3c1a08ee", - "displayName": "emoji icons", - "parentFolder": "6390c49774a71f99f21a08eb", - "assets": ["63e5889e7fe4eafa7384cea4", "659595234426a9fcbad57043"], - "siteId": "6390c49674a71f84b51a08d8", - "createdOn": "2018-10-14T21:55:49Z", - "lastUpdated": "2022-12-07T16:51:37Z", - } - ], - "pagination": {"limit": 1, "offset": 0, "total": 1}, - } - expected_types: typing.Any = { - "assetFolders": ( - "list", - { - 0: { - "id": None, - "displayName": None, - "parentFolder": None, - "assets": ("list", {0: None, 1: None}), - "siteId": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - } - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.assets.list_folders(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.assets.list_folders(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_create_folder(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "6390c49774a71f0e3c1a08ee", - "displayName": "emoji icons", - "parentFolder": "6390c49774a71f99f21a08eb", - "assets": ["63e5889e7fe4eafa7384cea4", "659595234426a9fcbad57043"], - "siteId": "6390c49674a71f84b51a08d8", - "createdOn": "2018-10-14T21:55:49Z", - "lastUpdated": "2022-12-07T16:51:37Z", - } - expected_types: typing.Any = { - "id": None, - "displayName": None, - "parentFolder": None, - "assets": ("list", {0: None, 1: None}), - "siteId": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - } - response = client.assets.create_folder(site_id="580e63e98c9a982ac9b8b741", display_name="my asset folder") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.assets.create_folder( - site_id="580e63e98c9a982ac9b8b741", display_name="my asset folder" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get_folder(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "6390c49774a71f0e3c1a08ee", - "displayName": "emoji icons", - "parentFolder": "6390c49774a71f99f21a08eb", - "assets": ["63e5889e7fe4eafa7384cea4", "659595234426a9fcbad57043"], - "siteId": "6390c49674a71f84b51a08d8", - "createdOn": "2018-10-14T21:55:49Z", - "lastUpdated": "2022-12-07T16:51:37Z", - } - expected_types: typing.Any = { - "id": None, - "displayName": None, - "parentFolder": None, - "assets": ("list", {0: None, 1: None}), - "siteId": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - } - response = client.assets.get_folder(asset_folder_id="6390c49774a71f0e3c1a08ee") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.assets.get_folder(asset_folder_id="6390c49774a71f0e3c1a08ee") - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_collections.py b/tests/test_collections.py deleted file mode 100644 index 4494869..0000000 --- a/tests/test_collections.py +++ /dev/null @@ -1,551 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response -from webflow import StaticField -from webflow import ReferenceField -from webflow import ReferenceFieldMetadata - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "collections": [ - { - "id": "63692ab61fb2852f582ba8f5", - "displayName": "Products", - "singularName": "Product", - "slug": "product", - "createdOn": "2019-06-12T13:35:14Z", - "lastUpdated": "2022-11-17T15:08:50Z", - }, - { - "id": "63692ab61fb2856e6a2ba8f6", - "displayName": "Categories", - "singularName": "Category", - "slug": "category", - "createdOn": "2019-06-12T13:35:14Z", - "lastUpdated": "2022-11-17T15:08:50Z", - }, - { - "id": "63692ab61fb285a8562ba8f4", - "displayName": "SKUs", - "singularName": "SKU", - "slug": "sku", - "createdOn": "2019-06-12T13:35:14Z", - "lastUpdated": "2022-11-17T15:08:50Z", - }, - ] - } - expected_types: typing.Any = { - "collections": ( - "list", - { - 0: { - "id": None, - "displayName": None, - "singularName": None, - "slug": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - }, - 1: { - "id": None, - "displayName": None, - "singularName": None, - "slug": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - }, - 2: { - "id": None, - "displayName": None, - "singularName": None, - "slug": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - }, - }, - ) - } - response = client.collections.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "562ac0395358780a1f5e6fbd", - "displayName": "Blog Posts", - "singularName": "Blog Post", - "slug": "posts", - "createdOn": "2016-10-24T19:41:48Z", - "lastUpdated": "2016-10-24T19:42:38Z", - "fields": [ - { - "id": "id", - "isRequired": True, - "isEditable": True, - "type": "PlainText", - "slug": "title", - "displayName": "Title", - "helpText": "The title of the blog post", - }, - { - "id": "id", - "isRequired": True, - "isEditable": True, - "type": "RichText", - "slug": "content", - "displayName": "Content", - "helpText": "The content of the blog post", - }, - { - "id": "id", - "isRequired": True, - "isEditable": True, - "type": "Reference", - "slug": "author", - "displayName": "Author", - "helpText": "The author of the blog post", - }, - ], - } - expected_types: typing.Any = { - "id": None, - "displayName": None, - "singularName": None, - "slug": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - "fields": ( - "list", - { - 0: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 1: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 2: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - }, - ), - } - response = client.collections.create( - site_id="580e63e98c9a982ac9b8b741", - display_name="Blog Posts", - singular_name="Blog Post", - slug="posts", - fields=[ - StaticField( - is_required=True, type="PlainText", display_name="Title", help_text="The title of the blog post" - ), - StaticField( - is_required=True, type="RichText", display_name="Content", help_text="The content of the blog post" - ), - ReferenceField( - is_required=True, - type="Reference", - display_name="Author", - help_text="The author of the blog post", - metadata=ReferenceFieldMetadata(collection_id="23cc2d952d4e4631ffd4345d2743db4e"), - ), - ], - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.create( - site_id="580e63e98c9a982ac9b8b741", - display_name="Blog Posts", - singular_name="Blog Post", - slug="posts", - fields=[ - StaticField( - is_required=True, type="PlainText", display_name="Title", help_text="The title of the blog post" - ), - StaticField( - is_required=True, type="RichText", display_name="Content", help_text="The content of the blog post" - ), - ReferenceField( - is_required=True, - type="Reference", - display_name="Author", - help_text="The author of the blog post", - metadata=ReferenceFieldMetadata(collection_id="23cc2d952d4e4631ffd4345d2743db4e"), - ), - ], - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "7f15043107e2fc95644e93807ee25dd6", - "displayName": "Guide Entries", - "singularName": "Guide Entry", - "slug": "guide-entry", - "createdOn": "2024-04-12T12:42:00Z", - "lastUpdated": "2024-04-12T12:42:00Z", - "fields": [ - { - "id": "5e2a1b3c4d5e6f7890a1b2c3", - "isRequired": True, - "isEditable": True, - "type": "PlainText", - "slug": "name", - "displayName": "Entry Title", - "helpText": "Name of the entry.", - }, - { - "id": "5e2a1b3c4d5e6f7890a1b2c4", - "isRequired": True, - "isEditable": True, - "type": "PlainText", - "slug": "slug", - "displayName": "Slug", - "helpText": "Slug of the entry.", - }, - { - "id": "6f7e8d9c0b1a2e3d4c5b6a7f", - "isRequired": False, - "isEditable": True, - "type": "PlainText", - "slug": "summary", - "displayName": "Summary", - "helpText": "A short summary of the entry.", - }, - { - "id": "1a2b3c4d5e6f7a8b9c0d1e2f", - "isRequired": False, - "isEditable": True, - "type": "RichText", - "slug": "entry-html", - "displayName": "Entry HTML", - "helpText": "The HTML content of the entry.", - }, - { - "id": "7e8d9c0b1a2e3d4c5b6a7f8e", - "isRequired": False, - "isEditable": True, - "type": "Image", - "slug": "illustration-image", - "displayName": "Illustration Image", - "helpText": "An image of the entry.", - }, - { - "id": "2f3e4d5c6b7a8e9d0c1b2a3f", - "isRequired": False, - "isEditable": True, - "type": "VideoLink", - "slug": "demonstration-video", - "displayName": "Demonstration Video", - "helpText": "A video of the entry.", - }, - { - "id": "8e9d0c1b2a3f4e5d6c7b8a9e", - "isRequired": False, - "isEditable": True, - "type": "Link", - "slug": "more-info-link", - "displayName": "More Info Link", - "helpText": "A link to more information about the entry.", - }, - { - "id": "3f4e5d6c7b8a9e0d1c2b3a4f", - "isRequired": False, - "isEditable": True, - "type": "Number", - "slug": "importance-level", - "displayName": "Importance Level", - "helpText": "The importance level of the entry.", - }, - { - "id": "9e0d1c2b3a4f5e6d7c8b9a0e", - "isRequired": False, - "isEditable": True, - "type": "Switch", - "slug": "is-essential", - "displayName": "Is Essential", - "helpText": "Is this entry essential?", - }, - { - "id": "4f5e6d7c8b9a0e1d2c3b4a5f", - "isRequired": False, - "isEditable": True, - "type": "Color", - "slug": "first-mentioned", - "displayName": "First Mentioned", - "helpText": "Date of the first mention of the subject.", - }, - { - "id": "0e1d2c3b4a5f6e7d8c9b0a1e", - "isRequired": False, - "isEditable": True, - "type": "Color", - "slug": "towel-color", - "displayName": "Towel Color", - "helpText": "The color of the towel.", - }, - { - "id": "5f6e7d8c9b0a1e2d3c4b5a6f", - "isRequired": False, - "isEditable": True, - "type": "Reference", - "slug": "related-entry", - "displayName": "Related Entry", - "helpText": "A related entry.", - }, - { - "id": "1e2d3c4b5a6f7e8d9c0b1a2f", - "isRequired": False, - "isEditable": True, - "type": "MultiReference", - "slug": "mentioned-in-entries", - "displayName": "Mentioned In Entries", - "helpText": "Entries that mention this subject.", - }, - { - "id": "6f7e8d9c0b1a2e3d4c5b6a8f", - "isRequired": False, - "isEditable": True, - "type": "Option", - "slug": "item-type", - "displayName": "Item Type", - "helpText": "The type of item.", - }, - { - "id": "2e3d4c5b6a7f8e9d0c1b2a4f", - "isRequired": False, - "isEditable": True, - "type": "File", - "slug": "guide-file", - "displayName": "Guide File", - "helpText": "helpText", - }, - { - "id": "7f8e9d0c1b2a3f4e5d6c8b9e", - "isRequired": False, - "isEditable": True, - "type": "Email", - "slug": "contributor-email", - "displayName": "Contributor Email", - "helpText": "helpText", - }, - { - "id": "3a4f5e6d7c8b9a0e1d2c4b5f", - "isRequired": False, - "isEditable": True, - "type": "Phone", - "slug": "emergency-contact", - "displayName": "Emergency Contact", - "helpText": "helpText", - }, - ], - } - expected_types: typing.Any = { - "id": None, - "displayName": None, - "singularName": None, - "slug": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - "fields": ( - "list", - { - 0: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 1: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 2: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 3: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 4: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 5: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 6: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 7: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 8: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 9: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 10: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 11: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 12: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 13: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 14: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 15: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - 16: { - "id": None, - "isRequired": None, - "isEditable": None, - "type": None, - "slug": None, - "displayName": None, - "helpText": None, - }, - }, - ), - } - response = client.collections.get(collection_id="580e63fc8c9a982ac9b8b745") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.collections.get(collection_id="580e63fc8c9a982ac9b8b745") - validate_response(async_response, expected_response, expected_types) - - -async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.collections.delete(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.collections.delete(collection_id="580e63fc8c9a982ac9b8b745") # type: ignore[func-returns-value] - is None - ) diff --git a/tests/test_components.py b/tests/test_components.py deleted file mode 100644 index c502ef0..0000000 --- a/tests/test_components.py +++ /dev/null @@ -1,311 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response -from webflow import TextNodeWrite -from webflow import Select -from webflow import SelectNodeWriteChoicesItem -from webflow import TextInputNodeWrite -from webflow import SubmitButtonNodeWrite -from webflow import ComponentInstanceNodePropertyOverridesWrite -from webflow import ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem -from webflow.resources.components import ComponentPropertiesWritePropertiesItem - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "components": [ - { - "id": "6596da6045e56dee495bcbba", - "name": "Primary Button", - "group": "Buttons", - "description": "A default button component that can be used across the site", - "readonly": True, - }, - { - "id": "658205daa3e8206a523b5ad4", - "name": "Secondary Button", - "group": "Buttons", - "description": "A secondary button component that can be used across the site", - "readonly": True, - }, - { - "id": "6258612d1ee792848f805dcf", - "name": "Card", - "group": "Buttons", - "description": "A button component that can be used across the site", - "readonly": True, - }, - { - "id": "68a2b1d1ee792848f805dcf", - "name": "Nav", - "group": "Buttons", - "description": "A button component that can be used across the site", - "readonly": True, - }, - ], - "pagination": {"limit": 20, "offset": 0, "total": 4}, - } - expected_types: typing.Any = { - "components": ( - "list", - { - 0: {"id": None, "name": None, "group": None, "description": None, "readonly": None}, - 1: {"id": None, "name": None, "group": None, "description": None, "readonly": None}, - 2: {"id": None, "name": None, "group": None, "description": None, "readonly": None}, - 3: {"id": None, "name": None, "group": None, "description": None, "readonly": None}, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.components.list( - site_id="580e63e98c9a982ac9b8b741", branch_id="68026fa68ef6dc744c75b833", limit=1, offset=1 - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.components.list( - site_id="580e63e98c9a982ac9b8b741", branch_id="68026fa68ef6dc744c75b833", limit=1, offset=1 - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get_content(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "componentId": "69118560-d0bc-15fc-bbf8-b8fe5f6535b5", - "nodes": [ - {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, - {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, - {"id": "id", "image": {}, "attributes": {"key": "value"}, "type": "image"}, - {"id": "id", "placeholder": "placeholder", "attributes": {"key": "value"}, "type": "text-input"}, - { - "id": "id", - "choices": [{"value": "value", "text": "text"}], - "attributes": {"key": "value"}, - "type": "select", - }, - { - "id": "id", - "value": "value", - "waitingText": "waitingText", - "attributes": {"key": "value"}, - "type": "submit-button", - }, - { - "id": "id", - "componentId": "componentId", - "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], - "type": "component-instance", - }, - ], - "pagination": {"limit": 7, "offset": 0, "total": 7}, - } - expected_types: typing.Any = { - "componentId": None, - "nodes": ( - "list", - { - 0: "no_validate", - 1: "no_validate", - 2: "no_validate", - 3: "no_validate", - 4: "no_validate", - 5: "no_validate", - 6: "no_validate", - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.components.get_content( - site_id="580e63e98c9a982ac9b8b741", - component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", - locale_id="65427cf400e02b306eaa04a0", - branch_id="68026fa68ef6dc744c75b833", - limit=1, - offset=1, - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.components.get_content( - site_id="580e63e98c9a982ac9b8b741", - component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", - locale_id="65427cf400e02b306eaa04a0", - branch_id="68026fa68ef6dc744c75b833", - limit=1, - offset=1, - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_update_content(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = {"errors": ["errors"]} - expected_types: typing.Any = {"errors": ("list", {0: None})} - response = client.components.update_content( - site_id="580e63e98c9a982ac9b8b741", - component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", - locale_id="65427cf400e02b306eaa04a0", - branch_id="68026fa68ef6dc744c75b833", - nodes=[ - TextNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

" - ), - TextNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", - text="

Don't Panic!

Always know where your towel is.

", - ), - Select( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", - choices=[ - SelectNodeWriteChoicesItem(value="choice-1", text="First choice"), - SelectNodeWriteChoicesItem(value="choice-2", text="Second choice"), - ], - ), - TextInputNodeWrite(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", placeholder="Enter something here..."), - SubmitButtonNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", value="Submit", waiting_text="Submitting..." - ), - ComponentInstanceNodePropertyOverridesWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", - property_overrides=[ - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", - text="

Time is an illusion

", - ), - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", text="Life, the Universe and Everything" - ), - ], - ), - ], - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.components.update_content( - site_id="580e63e98c9a982ac9b8b741", - component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", - locale_id="65427cf400e02b306eaa04a0", - branch_id="68026fa68ef6dc744c75b833", - nodes=[ - TextNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

" - ), - TextNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", - text="

Don't Panic!

Always know where your towel is.

", - ), - Select( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", - choices=[ - SelectNodeWriteChoicesItem(value="choice-1", text="First choice"), - SelectNodeWriteChoicesItem(value="choice-2", text="Second choice"), - ], - ), - TextInputNodeWrite(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", placeholder="Enter something here..."), - SubmitButtonNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", value="Submit", waiting_text="Submitting..." - ), - ComponentInstanceNodePropertyOverridesWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", - property_overrides=[ - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", - text="

Time is an illusion

", - ), - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", text="Life, the Universe and Everything" - ), - ], - ), - ], - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get_properties(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "componentId": "658205daa3e8206a523b5ad4", - "properties": [ - { - "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad623", - "type": "Plain Text", - "label": "Title", - "text": {"text": "The Hitchhiker's Guide to the Galaxy"}, - }, - { - "propertyId": "a245c12d-995b-55ee-5ec7-aa36a6cad627", - "type": "Rich Text", - "label": "Content", - "text": {"html": "

Don't Panic!

Always know where your towel is.

"}, - }, - ], - "pagination": {"limit": 2, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "componentId": None, - "properties": ( - "list", - { - 0: {"propertyId": None, "type": None, "label": None, "text": {"text": None}}, - 1: {"propertyId": None, "type": None, "label": None, "text": {"html": None}}, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.components.get_properties( - site_id="580e63e98c9a982ac9b8b741", - component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", - locale_id="65427cf400e02b306eaa04a0", - branch_id="68026fa68ef6dc744c75b833", - limit=1, - offset=1, - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.components.get_properties( - site_id="580e63e98c9a982ac9b8b741", - component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", - locale_id="65427cf400e02b306eaa04a0", - branch_id="68026fa68ef6dc744c75b833", - limit=1, - offset=1, - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_update_properties(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = {"errors": ["errors"]} - expected_types: typing.Any = {"errors": ("list", {0: None})} - response = client.components.update_properties( - site_id="580e63e98c9a982ac9b8b741", - component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", - locale_id="65427cf400e02b306eaa04a0", - branch_id="68026fa68ef6dc744c75b833", - properties=[ - ComponentPropertiesWritePropertiesItem( - property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="The Hitchhiker’s Guide to the Galaxy" - ), - ComponentPropertiesWritePropertiesItem( - property_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", - text="

Dont Panic!

Always know where your towel is.

", - ), - ], - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.components.update_properties( - site_id="580e63e98c9a982ac9b8b741", - component_id="8505ba55-ef72-629e-f85c-33e4b703d48b", - locale_id="65427cf400e02b306eaa04a0", - branch_id="68026fa68ef6dc744c75b833", - properties=[ - ComponentPropertiesWritePropertiesItem( - property_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="The Hitchhiker’s Guide to the Galaxy" - ), - ComponentPropertiesWritePropertiesItem( - property_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", - text="

Dont Panic!

Always know where your towel is.

", - ), - ], - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_ecommerce.py b/tests/test_ecommerce.py deleted file mode 100644 index b33a06f..0000000 --- a/tests/test_ecommerce.py +++ /dev/null @@ -1,20 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response - - -async def test_get_settings(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "siteId": "5eb0b5583bf24e2d3a488969", - "createdOn": "2018-10-04T15:21:02Z", - "defaultCurrency": "USD", - } - expected_types: typing.Any = {"siteId": None, "createdOn": "datetime", "defaultCurrency": None} - response = client.ecommerce.get_settings(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.ecommerce.get_settings(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_forms.py b/tests/test_forms.py deleted file mode 100644 index 8ca6e40..0000000 --- a/tests/test_forms.py +++ /dev/null @@ -1,291 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "forms": [ - { - "displayName": "Email Form", - "createdOn": "2016-10-24T19:41:29Z", - "lastUpdated": "2016-10-24T19:43:17Z", - "fields": { - "0": {"displayName": "Email", "placeholder": "Enter your email", "userVisible": True}, - "1": {"displayName": "Email", "placeholder": "Enter your email", "userVisible": True}, - }, - "responseSettings": { - "redirectUrl": "https://example.com", - "redirectMethod": "GET", - "redirectAction": "POST https://example.com", - "sendEmailConfirmation": True, - }, - "id": "589a331aa51e760df7ccb89e", - "siteId": "580e63e98c9a982ac9b8b741", - "siteDomainId": "6419db964a9c436a4baf6248", - "pageId": "6419db964a9c43f6a3af6348", - "pageName": "Home", - "formElementId": "4e038d2c-6a1e-4953-7be9-a59a2b453177", - "workspaceId": "580e63fc8c9a982ac9b8b744", - }, - { - "displayName": "Name Form", - "createdOn": "2016-10-24T19:41:29Z", - "lastUpdated": "2016-10-24T19:43:17Z", - "fields": {"0": {"displayName": "Email", "placeholder": "Enter your email", "userVisible": True}}, - "responseSettings": { - "redirectUrl": "https://example.com", - "redirectMethod": "GET", - "redirectAction": "POST https://example.com", - "sendEmailConfirmation": False, - }, - "id": "580ff8d7ba3e45ba9fe588e9", - "siteId": "580e63e98c9a982ac9b8b741", - "siteDomainId": "6419db964a9c436a4baf6248", - "pageId": "6419db964a9c43f6a3af6348", - "pageName": "Home", - "formElementId": "4e038d2c-6a1e-4953-7be9-a59a2b453177", - "workspaceId": "580e63fc8c9a982ac9b8b744", - }, - ], - "pagination": {"limit": 25, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "forms": ( - "list", - { - 0: { - "displayName": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - "fields": ( - "dict", - { - 0: (None, {"displayName": None, "placeholder": None, "userVisible": None}), - 1: (None, {"displayName": None, "placeholder": None, "userVisible": None}), - }, - ), - "responseSettings": { - "redirectUrl": None, - "redirectMethod": None, - "redirectAction": None, - "sendEmailConfirmation": None, - }, - "id": None, - "siteId": None, - "siteDomainId": None, - "pageId": None, - "pageName": None, - "formElementId": None, - "workspaceId": None, - }, - 1: { - "displayName": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - "fields": ("dict", {0: (None, {"displayName": None, "placeholder": None, "userVisible": None})}), - "responseSettings": { - "redirectUrl": None, - "redirectMethod": None, - "redirectAction": None, - "sendEmailConfirmation": None, - }, - "id": None, - "siteId": None, - "siteDomainId": None, - "pageId": None, - "pageName": None, - "formElementId": None, - "workspaceId": None, - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.forms.list(site_id="580e63e98c9a982ac9b8b741", limit=1, offset=1) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.forms.list(site_id="580e63e98c9a982ac9b8b741", limit=1, offset=1) - validate_response(async_response, expected_response, expected_types) - - -async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "displayName": "Email Form", - "createdOn": "2016-10-24T19:41:29Z", - "lastUpdated": "2016-10-24T19:43:17Z", - "fields": { - "660d5bcc9c0772150459dfb1": { - "displayName": "Name", - "type": "Plain", - "placeholder": "Enter your email", - "userVisible": True, - }, - "589a331aa51e760df7ccb89d": { - "displayName": "Email", - "type": "Email", - "placeholder": "Enter your email", - "userVisible": True, - }, - }, - "responseSettings": { - "redirectUrl": "https://example.com", - "redirectMethod": "GET", - "redirectAction": "POST https://example.com", - "sendEmailConfirmation": True, - }, - "id": "589a331aa51e760df7ccb89e", - "siteId": "580e63e98c9a982ac9b8b741", - "siteDomainId": "6419db964a9c436a4baf6248", - "pageId": "6419db964a9c43f6a3af6348", - "pageName": "Home", - "formElementId": "4e038d2c-6a1e-4953-7be9-a59a2b453177", - "workspaceId": "580e63fc8c9a982ac9b8b744", - } - expected_types: typing.Any = { - "displayName": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - "fields": ( - "dict", - { - 0: (None, {"displayName": None, "type": None, "placeholder": None, "userVisible": None}), - 1: (None, {"displayName": None, "type": None, "placeholder": None, "userVisible": None}), - }, - ), - "responseSettings": { - "redirectUrl": None, - "redirectMethod": None, - "redirectAction": None, - "sendEmailConfirmation": None, - }, - "id": None, - "siteId": None, - "siteDomainId": None, - "pageId": None, - "pageName": None, - "formElementId": None, - "workspaceId": None, - } - response = client.forms.get(form_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.forms.get(form_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_list_submissions(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "formSubmissions": [ - { - "id": "6321ca84df3949bfc6752327", - "displayName": "Sample Form", - "siteId": "62749158efef318abc8d5a0f", - "workspaceId": "62749158efef318abc8d5a0f", - "dateSubmitted": "2022-09-14T12:35:16Z", - "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, - }, - { - "id": "660d64fabf6e0a0d4edab981", - "displayName": "Sample Form", - "siteId": "62749158efef318abc8d5a0f", - "workspaceId": "62749158efef318abc8d5a0f", - "dateSubmitted": "2022-09-14T12:35:16Z", - "formResponse": {"First Name": "Ford", "Last Name": "Prefect"}, - }, - ], - "pagination": {"limit": 25, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "formSubmissions": ( - "list", - { - 0: { - "id": None, - "displayName": None, - "siteId": None, - "workspaceId": None, - "dateSubmitted": "datetime", - "formResponse": ("dict", {0: (None, None), 1: (None, None)}), - }, - 1: { - "id": None, - "displayName": None, - "siteId": None, - "workspaceId": None, - "dateSubmitted": "datetime", - "formResponse": ("dict", {0: (None, None), 1: (None, None)}), - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.forms.list_submissions(form_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.forms.list_submissions(form_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) - validate_response(async_response, expected_response, expected_types) - - -async def test_get_submission(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "6321ca84df3949bfc6752327", - "displayName": "Sample Form", - "siteId": "62749158efef318abc8d5a0f", - "workspaceId": "62749158efef318abc8d5a0f", - "dateSubmitted": "2022-09-14T12:35:16Z", - "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, - } - expected_types: typing.Any = { - "id": None, - "displayName": None, - "siteId": None, - "workspaceId": None, - "dateSubmitted": "datetime", - "formResponse": ("dict", {0: (None, None), 1: (None, None)}), - } - response = client.forms.get_submission(form_submission_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.forms.get_submission(form_submission_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_delete_submission(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.forms.delete_submission(form_submission_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.forms.delete_submission(form_submission_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] - is None - ) - - -async def test_update_submission(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "6321ca84df3949bfc6752327", - "displayName": "Sample Form", - "siteId": "62749158efef318abc8d5a0f", - "workspaceId": "62749158efef318abc8d5a0f", - "dateSubmitted": "2022-09-14T12:35:16Z", - "formResponse": {"First Name": "Arthur", "Last Name": "Dent"}, - } - expected_types: typing.Any = { - "id": None, - "displayName": None, - "siteId": None, - "workspaceId": None, - "dateSubmitted": "datetime", - "formResponse": ("dict", {0: (None, None), 1: (None, None)}), - } - response = client.forms.update_submission(form_submission_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.forms.update_submission(form_submission_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_inventory.py b/tests/test_inventory.py deleted file mode 100644 index 95062f9..0000000 --- a/tests/test_inventory.py +++ /dev/null @@ -1,32 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = {"id": "5bfedb42bab0ad90fa7dad39", "quantity": 100, "inventoryType": "finite"} - expected_types: typing.Any = {"id": None, "quantity": None, "inventoryType": None} - response = client.inventory.list(sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.inventory.list( - sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = {"id": "5bfedb42bab0ad90fa7dad39", "quantity": 100, "inventoryType": "finite"} - expected_types: typing.Any = {"id": None, "quantity": None, "inventoryType": None} - response = client.inventory.update( - sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415", inventory_type="infinite" - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.inventory.update( - sku_collection_id="6377a7c4b7a79608c34a46f7", sku_id="5e8518516e147040726cc415", inventory_type="infinite" - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_orders.py b/tests/test_orders.py deleted file mode 100644 index dce7836..0000000 --- a/tests/test_orders.py +++ /dev/null @@ -1,2337 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "orders": [ - { - "orderId": "7c1-9fd", - "status": "unfulfilled", - "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", - "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', - "acceptedOn": "2024-04-10T13:16:21Z", - "fulfilledOn": "2018-12-03T22:06:15Z", - "refundedOn": "2018-12-03T22:06:15Z", - "disputedOn": "2018-12-03T22:06:15Z", - "disputeUpdatedOn": "2018-12-03T22:06:15Z", - "disputeLastStatus": "warning_needs_response", - "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 211.55 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": "$ 200.89 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 4.23 USD"}, - "allAddresses": [ - { - "type": "billing", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - { - "type": "shipping", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - ], - "shippingAddress": { - "type": "shipping", - "japanType": "kanji", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "billingAddress": { - "type": "billing", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "shippingProvider": "Shipping Company, Co.", - "shippingTracking": "tr00000000002", - "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000002", - "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, - "purchasedItems": [ - { - "count": 2, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 111.22 USD"}, - "productId": "66072fb61b89448912e26791", - "productName": "Luxurious Fresh Ball", - "productSlug": "luxurious-fresh-ball", - "variantId": "66072fb71b89448912e2683f", - "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", - "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "weight": 11, - "width": 82, - "height": 70, - "length": 9, - }, - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 83.09 USD"}, - "productId": "66072fb61b89448912e2678b", - "productName": "Incredible Bronze Towels", - "productSlug": "incredible-bronze-towels", - "variantId": "66072fb71b89448912e2681e", - "variantName": "Incredible Bronze Towels Sleek: Frozen, Incredible: Metal", - "variantSlug": "incredible-bronze-towels-sleek-frozen-incredible-metal", - "variantSKU": "incredible-bronze-towels-sleek-frozen-incredible-metal", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e26729_image16.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 83.09 USD"}, - "weight": 5, - "width": 19, - "height": 72, - "length": 18, - }, - ], - "purchasedItemsCount": 3, - "stripeDetails": { - "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", - "paymentMethod": "pm_1P410gJYFi4lcbXWbeKghqjK", - "paymentIntentId": "pi_3P410iJYFi4lcbXW0EKKgcVg", - "customerId": "cus_Ptod8KJBiiPgnH", - "chargeId": "ch_3P410iJYFi4lcbXW0DxUkzCH", - "refundReason": "requested_by_customer", - }, - "stripeCard": { - "last4": "4242", - "brand": "Visa", - "ownerName": "Arthur Dent", - "expires": {"year": 2025, "month": 4}, - }, - "paypalDetails": { - "orderId": "1a2b3c4d5e6f7g8h9i0j", - "payerId": "9k8j7i6h5g4f3e2d1c0b", - "captureId": "qwe123rty456uio789p", - "refundId": "abcde12345fghij67890", - "refundReason": "Customer requested refund", - "disputeId": "zxcvbnm987poiuytrewq", - }, - "customData": [{"key": "value"}], - "metadata": {"isBuyNow": False}, - "isCustomerDeleted": False, - "isShippingRequired": False, - "hasDownloads": False, - "paymentProcessor": "stripe", - "totals": { - "extras": [ - { - "type": "tax", - "name": "State Taxes", - "description": "CA Taxes (6.25%)", - "price": {"unit": "USD", "value": "5892", "string": "$3.44"}, - } - ] - }, - "downloadFiles": [ - { - "id": "5e9a5eba75e0ac242e1b6f64", - "name": "The modern web design process - Webflow Ebook.pdf", - "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", - } - ], - }, - { - "orderId": "fc7-128", - "status": "refunded", - "comment": "Example comment to myself", - "orderComment": "", - "acceptedOn": "2024-03-29T21:29:21Z", - "fulfilledOn": "2018-12-03T22:06:15Z", - "refundedOn": "2024-04-08T18:25:04Z", - "disputedOn": "2018-12-03T22:06:15Z", - "disputeUpdatedOn": "2018-12-03T22:06:15Z", - "disputeLastStatus": "warning_needs_response", - "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, - "allAddresses": [ - { - "type": "billing", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - { - "type": "shipping", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - ], - "shippingAddress": { - "type": "shipping", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "billingAddress": { - "type": "billing", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "shippingProvider": "Shipping Company, Co.", - "shippingTracking": "tr00000000001", - "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", - "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, - "purchasedItems": [ - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "productId": "66072fb61b89448912e26791", - "productName": "Luxurious Fresh Ball", - "productSlug": "luxurious-fresh-ball", - "variantId": "66072fb71b89448912e2683f", - "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", - "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "weight": 11, - "width": 82, - "height": 70, - "length": 9, - }, - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "productId": "66072fb61b89448912e26799", - "productName": "Recycled Steel Gloves", - "productSlug": "recycled-steel-gloves", - "variantId": "66072fb91b89448912e26ab9", - "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", - "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "weight": 38, - "width": 76, - "height": 85, - "length": 40, - }, - ], - "purchasedItemsCount": 2, - "stripeDetails": { - "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", - "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", - "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", - "customerId": "cus_PpRsNHwWdUoRKR", - "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", - "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", - "refundReason": "fraudulent", - }, - "stripeCard": { - "last4": "4242", - "brand": "Visa", - "ownerName": "Arthur Dent", - "expires": {"year": 2024, "month": 4}, - }, - "paypalDetails": { - "orderId": "1a2b3c4d5e6f7g8h9i0j", - "payerId": "9k8j7i6h5g4f3e2d1c0b", - "captureId": "qwe123rty456uio789p", - "refundId": "abcde12345fghij67890", - "refundReason": "Customer requested refund", - "disputeId": "zxcvbnm987poiuytrewq", - }, - "customData": [{"key": "value"}], - "metadata": {"isBuyNow": False}, - "isCustomerDeleted": False, - "isShippingRequired": True, - "hasDownloads": False, - "paymentProcessor": "stripe", - "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, - "extras": [ - { - "type": "tax", - "name": "State Taxes", - "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, - }, - { - "type": "tax", - "name": "City Taxes", - "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, - }, - { - "type": "shipping", - "name": "Flat", - "description": "", - "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, - }, - ], - "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - }, - "downloadFiles": [ - { - "id": "5e9a5eba75e0ac242e1b6f64", - "name": "New product guide", - "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", - } - ], - }, - ], - "pagination": {"limit": 100, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "orders": ( - "list", - { - 0: { - "orderId": None, - "status": None, - "comment": None, - "orderComment": None, - "acceptedOn": "datetime", - "fulfilledOn": "datetime", - "refundedOn": "datetime", - "disputedOn": "datetime", - "disputeUpdatedOn": "datetime", - "disputeLastStatus": None, - "customerPaid": {"unit": None, "value": None, "string": None}, - "netAmount": {"unit": None, "value": None, "string": None}, - "applicationFee": {"unit": None, "value": None, "string": None}, - "allAddresses": ( - "list", - { - 0: { - "type": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - 1: { - "type": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - }, - ), - "shippingAddress": { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "billingAddress": { - "type": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "shippingProvider": None, - "shippingTracking": None, - "shippingTrackingURL": None, - "customerInfo": {"fullName": None, "email": None}, - "purchasedItems": ( - "list", - { - 0: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - 1: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - }, - ), - "purchasedItemsCount": None, - "stripeDetails": { - "subscriptionId": None, - "paymentMethod": None, - "paymentIntentId": None, - "customerId": None, - "chargeId": None, - "refundReason": None, - }, - "stripeCard": { - "last4": None, - "brand": None, - "ownerName": None, - "expires": {"year": None, "month": None}, - }, - "paypalDetails": { - "orderId": None, - "payerId": None, - "captureId": None, - "refundId": None, - "refundReason": None, - "disputeId": None, - }, - "customData": ("list", {0: ("dict", {0: (None, None)})}), - "metadata": {"isBuyNow": None}, - "isCustomerDeleted": None, - "isShippingRequired": None, - "hasDownloads": None, - "paymentProcessor": None, - "totals": { - "extras": ( - "list", - { - 0: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - } - }, - ) - }, - "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), - }, - 1: { - "orderId": None, - "status": None, - "comment": None, - "orderComment": None, - "acceptedOn": "datetime", - "fulfilledOn": "datetime", - "refundedOn": "datetime", - "disputedOn": "datetime", - "disputeUpdatedOn": "datetime", - "disputeLastStatus": None, - "customerPaid": {"unit": None, "value": None, "string": None}, - "netAmount": {"unit": None, "value": None, "string": None}, - "applicationFee": {"unit": None, "value": None, "string": None}, - "allAddresses": ( - "list", - { - 0: { - "type": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - 1: { - "type": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - }, - ), - "shippingAddress": { - "type": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "billingAddress": { - "type": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "shippingProvider": None, - "shippingTracking": None, - "shippingTrackingURL": None, - "customerInfo": {"fullName": None, "email": None}, - "purchasedItems": ( - "list", - { - 0: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - 1: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - }, - ), - "purchasedItemsCount": None, - "stripeDetails": { - "subscriptionId": None, - "paymentMethod": None, - "paymentIntentId": None, - "customerId": None, - "chargeId": None, - "refundId": None, - "refundReason": None, - }, - "stripeCard": { - "last4": None, - "brand": None, - "ownerName": None, - "expires": {"year": None, "month": None}, - }, - "paypalDetails": { - "orderId": None, - "payerId": None, - "captureId": None, - "refundId": None, - "refundReason": None, - "disputeId": None, - }, - "customData": ("list", {0: ("dict", {0: (None, None)})}), - "metadata": {"isBuyNow": None}, - "isCustomerDeleted": None, - "isShippingRequired": None, - "hasDownloads": None, - "paymentProcessor": None, - "totals": { - "subtotal": {"unit": None, "value": None, "string": None}, - "extras": ( - "list", - { - 0: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 1: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 2: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - }, - ), - "total": {"unit": None, "value": None, "string": None}, - }, - "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.orders.list(site_id="580e63e98c9a982ac9b8b741", status="pending", offset=1, limit=1) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.orders.list( - site_id="580e63e98c9a982ac9b8b741", status="pending", offset=1, limit=1 - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "orderId": "fc7-128", - "status": "refunded", - "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", - "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', - "acceptedOn": "2024-03-29T21:29:21Z", - "fulfilledOn": "2024-03-29T21:29:21Z", - "refundedOn": "2024-04-08T18:25:04Z", - "disputedOn": "2024-03-29T21:29:21Z", - "disputeUpdatedOn": "2024-03-29T21:29:21Z", - "disputeLastStatus": "charge_refunded", - "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, - "allAddresses": [ - { - "type": "billing", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - { - "type": "shipping", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - ], - "shippingAddress": { - "type": "shipping", - "japanType": "kanji", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "billingAddress": { - "type": "billing", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "shippingProvider": "Shipping Company, Co.", - "shippingTracking": "tr00000000001", - "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", - "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, - "purchasedItems": [ - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "productId": "66072fb61b89448912e26791", - "productName": "Luxurious Fresh Ball", - "productSlug": "luxurious-fresh-ball", - "variantId": "66072fb71b89448912e2683f", - "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", - "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "weight": 11, - "width": 82, - "height": 70, - "length": 9, - }, - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "productId": "66072fb61b89448912e26799", - "productName": "Recycled Steel Gloves", - "productSlug": "recycled-steel-gloves", - "variantId": "66072fb91b89448912e26ab9", - "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", - "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "weight": 38, - "width": 76, - "height": 85, - "length": 40, - }, - ], - "purchasedItemsCount": 2, - "stripeDetails": { - "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", - "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", - "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", - "customerId": "cus_PpRsNHwWdUoRKR", - "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", - "disputeId": "disputeId", - "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", - "refundReason": "fraudulent", - }, - "stripeCard": { - "last4": "4242", - "brand": "Visa", - "ownerName": "Arthur Dent", - "expires": {"year": 2024, "month": 4}, - }, - "paypalDetails": { - "orderId": "1a2b3c4d5e6f7g8h9i0j", - "payerId": "9k8j7i6h5g4f3e2d1c0b", - "captureId": "qwe123rty456uio789p", - "refundId": "abcde12345fghij67890", - "refundReason": "Customer requested refund", - "disputeId": "zxcvbnm987poiuytrewq", - }, - "customData": [{"key": "value"}], - "metadata": {"isBuyNow": False}, - "isCustomerDeleted": False, - "isShippingRequired": True, - "hasDownloads": False, - "paymentProcessor": "stripe", - "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, - "extras": [ - { - "type": "tax", - "name": "State Taxes", - "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, - }, - { - "type": "tax", - "name": "City Taxes", - "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, - }, - { - "type": "shipping", - "name": "Flat", - "description": "", - "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, - }, - ], - "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - }, - "downloadFiles": [ - { - "id": "5e9a5eba75e0ac242e1b6f64", - "name": "New product guide", - "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", - } - ], - } - expected_types: typing.Any = { - "orderId": None, - "status": None, - "comment": None, - "orderComment": None, - "acceptedOn": "datetime", - "fulfilledOn": "datetime", - "refundedOn": "datetime", - "disputedOn": "datetime", - "disputeUpdatedOn": "datetime", - "disputeLastStatus": None, - "customerPaid": {"unit": None, "value": None, "string": None}, - "netAmount": {"unit": None, "value": None, "string": None}, - "applicationFee": {"unit": None, "value": None, "string": None}, - "allAddresses": ( - "list", - { - 0: { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - 1: { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - }, - ), - "shippingAddress": { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "billingAddress": { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "shippingProvider": None, - "shippingTracking": None, - "shippingTrackingURL": None, - "customerInfo": {"fullName": None, "email": None}, - "purchasedItems": ( - "list", - { - 0: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - 1: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - }, - ), - "purchasedItemsCount": None, - "stripeDetails": { - "subscriptionId": None, - "paymentMethod": None, - "paymentIntentId": None, - "customerId": None, - "chargeId": None, - "disputeId": None, - "refundId": None, - "refundReason": None, - }, - "stripeCard": {"last4": None, "brand": None, "ownerName": None, "expires": {"year": None, "month": None}}, - "paypalDetails": { - "orderId": None, - "payerId": None, - "captureId": None, - "refundId": None, - "refundReason": None, - "disputeId": None, - }, - "customData": ("list", {0: ("dict", {0: (None, None)})}), - "metadata": {"isBuyNow": None}, - "isCustomerDeleted": None, - "isShippingRequired": None, - "hasDownloads": None, - "paymentProcessor": None, - "totals": { - "subtotal": {"unit": None, "value": None, "string": None}, - "extras": ( - "list", - { - 0: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 1: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 2: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - }, - ), - "total": {"unit": None, "value": None, "string": None}, - }, - "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), - } - response = client.orders.get(site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.orders.get( - site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "orderId": "fc7-128", - "status": "refunded", - "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", - "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', - "acceptedOn": "2024-03-29T21:29:21Z", - "fulfilledOn": "2024-03-29T21:29:21Z", - "refundedOn": "2024-04-08T18:25:04Z", - "disputedOn": "2024-03-29T21:29:21Z", - "disputeUpdatedOn": "2024-03-29T21:29:21Z", - "disputeLastStatus": "charge_refunded", - "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, - "allAddresses": [ - { - "type": "billing", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - { - "type": "shipping", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - ], - "shippingAddress": { - "type": "shipping", - "japanType": "kanji", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "billingAddress": { - "type": "billing", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "shippingProvider": "Shipping Company, Co.", - "shippingTracking": "tr00000000001", - "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", - "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, - "purchasedItems": [ - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "productId": "66072fb61b89448912e26791", - "productName": "Luxurious Fresh Ball", - "productSlug": "luxurious-fresh-ball", - "variantId": "66072fb71b89448912e2683f", - "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", - "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "weight": 11, - "width": 82, - "height": 70, - "length": 9, - }, - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "productId": "66072fb61b89448912e26799", - "productName": "Recycled Steel Gloves", - "productSlug": "recycled-steel-gloves", - "variantId": "66072fb91b89448912e26ab9", - "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", - "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "weight": 38, - "width": 76, - "height": 85, - "length": 40, - }, - ], - "purchasedItemsCount": 2, - "stripeDetails": { - "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", - "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", - "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", - "customerId": "cus_PpRsNHwWdUoRKR", - "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", - "disputeId": "disputeId", - "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", - "refundReason": "fraudulent", - }, - "stripeCard": { - "last4": "4242", - "brand": "Visa", - "ownerName": "Arthur Dent", - "expires": {"year": 2024, "month": 4}, - }, - "paypalDetails": { - "orderId": "1a2b3c4d5e6f7g8h9i0j", - "payerId": "9k8j7i6h5g4f3e2d1c0b", - "captureId": "qwe123rty456uio789p", - "refundId": "abcde12345fghij67890", - "refundReason": "Customer requested refund", - "disputeId": "zxcvbnm987poiuytrewq", - }, - "customData": [{"key": "value"}], - "metadata": {"isBuyNow": False}, - "isCustomerDeleted": False, - "isShippingRequired": True, - "hasDownloads": False, - "paymentProcessor": "stripe", - "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, - "extras": [ - { - "type": "tax", - "name": "State Taxes", - "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, - }, - { - "type": "tax", - "name": "City Taxes", - "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, - }, - { - "type": "shipping", - "name": "Flat", - "description": "", - "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, - }, - ], - "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - }, - "downloadFiles": [ - { - "id": "5e9a5eba75e0ac242e1b6f64", - "name": "New product guide", - "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", - } - ], - } - expected_types: typing.Any = { - "orderId": None, - "status": None, - "comment": None, - "orderComment": None, - "acceptedOn": "datetime", - "fulfilledOn": "datetime", - "refundedOn": "datetime", - "disputedOn": "datetime", - "disputeUpdatedOn": "datetime", - "disputeLastStatus": None, - "customerPaid": {"unit": None, "value": None, "string": None}, - "netAmount": {"unit": None, "value": None, "string": None}, - "applicationFee": {"unit": None, "value": None, "string": None}, - "allAddresses": ( - "list", - { - 0: { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - 1: { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - }, - ), - "shippingAddress": { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "billingAddress": { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "shippingProvider": None, - "shippingTracking": None, - "shippingTrackingURL": None, - "customerInfo": {"fullName": None, "email": None}, - "purchasedItems": ( - "list", - { - 0: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - 1: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - }, - ), - "purchasedItemsCount": None, - "stripeDetails": { - "subscriptionId": None, - "paymentMethod": None, - "paymentIntentId": None, - "customerId": None, - "chargeId": None, - "disputeId": None, - "refundId": None, - "refundReason": None, - }, - "stripeCard": {"last4": None, "brand": None, "ownerName": None, "expires": {"year": None, "month": None}}, - "paypalDetails": { - "orderId": None, - "payerId": None, - "captureId": None, - "refundId": None, - "refundReason": None, - "disputeId": None, - }, - "customData": ("list", {0: ("dict", {0: (None, None)})}), - "metadata": {"isBuyNow": None}, - "isCustomerDeleted": None, - "isShippingRequired": None, - "hasDownloads": None, - "paymentProcessor": None, - "totals": { - "subtotal": {"unit": None, "value": None, "string": None}, - "extras": ( - "list", - { - 0: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 1: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 2: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - }, - ), - "total": {"unit": None, "value": None, "string": None}, - }, - "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), - } - response = client.orders.update(site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.orders.update( - site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_update_fulfill(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "orderId": "fc7-128", - "status": "refunded", - "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", - "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', - "acceptedOn": "2024-03-29T21:29:21Z", - "fulfilledOn": "2024-03-29T21:29:21Z", - "refundedOn": "2024-04-08T18:25:04Z", - "disputedOn": "2024-03-29T21:29:21Z", - "disputeUpdatedOn": "2024-03-29T21:29:21Z", - "disputeLastStatus": "charge_refunded", - "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, - "allAddresses": [ - { - "type": "billing", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - { - "type": "shipping", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - ], - "shippingAddress": { - "type": "shipping", - "japanType": "kanji", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "billingAddress": { - "type": "billing", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "shippingProvider": "Shipping Company, Co.", - "shippingTracking": "tr00000000001", - "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", - "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, - "purchasedItems": [ - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "productId": "66072fb61b89448912e26791", - "productName": "Luxurious Fresh Ball", - "productSlug": "luxurious-fresh-ball", - "variantId": "66072fb71b89448912e2683f", - "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", - "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "weight": 11, - "width": 82, - "height": 70, - "length": 9, - }, - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "productId": "66072fb61b89448912e26799", - "productName": "Recycled Steel Gloves", - "productSlug": "recycled-steel-gloves", - "variantId": "66072fb91b89448912e26ab9", - "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", - "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "weight": 38, - "width": 76, - "height": 85, - "length": 40, - }, - ], - "purchasedItemsCount": 2, - "stripeDetails": { - "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", - "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", - "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", - "customerId": "cus_PpRsNHwWdUoRKR", - "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", - "disputeId": "disputeId", - "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", - "refundReason": "fraudulent", - }, - "stripeCard": { - "last4": "4242", - "brand": "Visa", - "ownerName": "Arthur Dent", - "expires": {"year": 2024, "month": 4}, - }, - "paypalDetails": { - "orderId": "1a2b3c4d5e6f7g8h9i0j", - "payerId": "9k8j7i6h5g4f3e2d1c0b", - "captureId": "qwe123rty456uio789p", - "refundId": "abcde12345fghij67890", - "refundReason": "Customer requested refund", - "disputeId": "zxcvbnm987poiuytrewq", - }, - "customData": [{"key": "value"}], - "metadata": {"isBuyNow": False}, - "isCustomerDeleted": False, - "isShippingRequired": True, - "hasDownloads": False, - "paymentProcessor": "stripe", - "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, - "extras": [ - { - "type": "tax", - "name": "State Taxes", - "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, - }, - { - "type": "tax", - "name": "City Taxes", - "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, - }, - { - "type": "shipping", - "name": "Flat", - "description": "", - "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, - }, - ], - "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - }, - "downloadFiles": [ - { - "id": "5e9a5eba75e0ac242e1b6f64", - "name": "New product guide", - "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", - } - ], - } - expected_types: typing.Any = { - "orderId": None, - "status": None, - "comment": None, - "orderComment": None, - "acceptedOn": "datetime", - "fulfilledOn": "datetime", - "refundedOn": "datetime", - "disputedOn": "datetime", - "disputeUpdatedOn": "datetime", - "disputeLastStatus": None, - "customerPaid": {"unit": None, "value": None, "string": None}, - "netAmount": {"unit": None, "value": None, "string": None}, - "applicationFee": {"unit": None, "value": None, "string": None}, - "allAddresses": ( - "list", - { - 0: { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - 1: { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - }, - ), - "shippingAddress": { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "billingAddress": { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "shippingProvider": None, - "shippingTracking": None, - "shippingTrackingURL": None, - "customerInfo": {"fullName": None, "email": None}, - "purchasedItems": ( - "list", - { - 0: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - 1: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - }, - ), - "purchasedItemsCount": None, - "stripeDetails": { - "subscriptionId": None, - "paymentMethod": None, - "paymentIntentId": None, - "customerId": None, - "chargeId": None, - "disputeId": None, - "refundId": None, - "refundReason": None, - }, - "stripeCard": {"last4": None, "brand": None, "ownerName": None, "expires": {"year": None, "month": None}}, - "paypalDetails": { - "orderId": None, - "payerId": None, - "captureId": None, - "refundId": None, - "refundReason": None, - "disputeId": None, - }, - "customData": ("list", {0: ("dict", {0: (None, None)})}), - "metadata": {"isBuyNow": None}, - "isCustomerDeleted": None, - "isShippingRequired": None, - "hasDownloads": None, - "paymentProcessor": None, - "totals": { - "subtotal": {"unit": None, "value": None, "string": None}, - "extras": ( - "list", - { - 0: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 1: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 2: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - }, - ), - "total": {"unit": None, "value": None, "string": None}, - }, - "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), - } - response = client.orders.update_fulfill(site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.orders.update_fulfill( - site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_update_unfulfill(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "orderId": "fc7-128", - "status": "refunded", - "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", - "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', - "acceptedOn": "2024-03-29T21:29:21Z", - "fulfilledOn": "2024-03-29T21:29:21Z", - "refundedOn": "2024-04-08T18:25:04Z", - "disputedOn": "2024-03-29T21:29:21Z", - "disputeUpdatedOn": "2024-03-29T21:29:21Z", - "disputeLastStatus": "charge_refunded", - "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, - "allAddresses": [ - { - "type": "billing", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - { - "type": "shipping", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - ], - "shippingAddress": { - "type": "shipping", - "japanType": "kanji", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "billingAddress": { - "type": "billing", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "shippingProvider": "Shipping Company, Co.", - "shippingTracking": "tr00000000001", - "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", - "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, - "purchasedItems": [ - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "productId": "66072fb61b89448912e26791", - "productName": "Luxurious Fresh Ball", - "productSlug": "luxurious-fresh-ball", - "variantId": "66072fb71b89448912e2683f", - "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", - "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "weight": 11, - "width": 82, - "height": 70, - "length": 9, - }, - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "productId": "66072fb61b89448912e26799", - "productName": "Recycled Steel Gloves", - "productSlug": "recycled-steel-gloves", - "variantId": "66072fb91b89448912e26ab9", - "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", - "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "weight": 38, - "width": 76, - "height": 85, - "length": 40, - }, - ], - "purchasedItemsCount": 2, - "stripeDetails": { - "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", - "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", - "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", - "customerId": "cus_PpRsNHwWdUoRKR", - "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", - "disputeId": "disputeId", - "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", - "refundReason": "fraudulent", - }, - "stripeCard": { - "last4": "4242", - "brand": "Visa", - "ownerName": "Arthur Dent", - "expires": {"year": 2024, "month": 4}, - }, - "paypalDetails": { - "orderId": "1a2b3c4d5e6f7g8h9i0j", - "payerId": "9k8j7i6h5g4f3e2d1c0b", - "captureId": "qwe123rty456uio789p", - "refundId": "abcde12345fghij67890", - "refundReason": "Customer requested refund", - "disputeId": "zxcvbnm987poiuytrewq", - }, - "customData": [{"key": "value"}], - "metadata": {"isBuyNow": False}, - "isCustomerDeleted": False, - "isShippingRequired": True, - "hasDownloads": False, - "paymentProcessor": "stripe", - "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, - "extras": [ - { - "type": "tax", - "name": "State Taxes", - "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, - }, - { - "type": "tax", - "name": "City Taxes", - "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, - }, - { - "type": "shipping", - "name": "Flat", - "description": "", - "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, - }, - ], - "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - }, - "downloadFiles": [ - { - "id": "5e9a5eba75e0ac242e1b6f64", - "name": "New product guide", - "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", - } - ], - } - expected_types: typing.Any = { - "orderId": None, - "status": None, - "comment": None, - "orderComment": None, - "acceptedOn": "datetime", - "fulfilledOn": "datetime", - "refundedOn": "datetime", - "disputedOn": "datetime", - "disputeUpdatedOn": "datetime", - "disputeLastStatus": None, - "customerPaid": {"unit": None, "value": None, "string": None}, - "netAmount": {"unit": None, "value": None, "string": None}, - "applicationFee": {"unit": None, "value": None, "string": None}, - "allAddresses": ( - "list", - { - 0: { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - 1: { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - }, - ), - "shippingAddress": { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "billingAddress": { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "shippingProvider": None, - "shippingTracking": None, - "shippingTrackingURL": None, - "customerInfo": {"fullName": None, "email": None}, - "purchasedItems": ( - "list", - { - 0: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - 1: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - }, - ), - "purchasedItemsCount": None, - "stripeDetails": { - "subscriptionId": None, - "paymentMethod": None, - "paymentIntentId": None, - "customerId": None, - "chargeId": None, - "disputeId": None, - "refundId": None, - "refundReason": None, - }, - "stripeCard": {"last4": None, "brand": None, "ownerName": None, "expires": {"year": None, "month": None}}, - "paypalDetails": { - "orderId": None, - "payerId": None, - "captureId": None, - "refundId": None, - "refundReason": None, - "disputeId": None, - }, - "customData": ("list", {0: ("dict", {0: (None, None)})}), - "metadata": {"isBuyNow": None}, - "isCustomerDeleted": None, - "isShippingRequired": None, - "hasDownloads": None, - "paymentProcessor": None, - "totals": { - "subtotal": {"unit": None, "value": None, "string": None}, - "extras": ( - "list", - { - 0: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 1: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 2: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - }, - ), - "total": {"unit": None, "value": None, "string": None}, - }, - "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), - } - response = client.orders.update_unfulfill(site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.orders.update_unfulfill( - site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_refund(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "orderId": "fc7-128", - "status": "refunded", - "comment": "Customer requested gift wrapping and a personalized note saying: Happy Birthday, Ford! 🎉 Please ensure the item is packed with extra bubble wrap for safe transit.", - "orderComment": 'Please gift wrap with a personal note saying "Happy Birthday, Ford! 🎉', - "acceptedOn": "2024-03-29T21:29:21Z", - "fulfilledOn": "2024-03-29T21:29:21Z", - "refundedOn": "2024-04-08T18:25:04Z", - "disputedOn": "2024-03-29T21:29:21Z", - "disputeUpdatedOn": "2024-03-29T21:29:21Z", - "disputeLastStatus": "charge_refunded", - "customerPaid": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - "netAmount": {"unit": "USD", "value": "5892", "string": "$ 112.62 USD"}, - "applicationFee": {"unit": "USD", "value": "5892", "string": "$ 2.37 USD"}, - "allAddresses": [ - { - "type": "billing", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - { - "type": "shipping", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - ], - "shippingAddress": { - "type": "shipping", - "japanType": "kanji", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "billingAddress": { - "type": "billing", - "japanType": "kana", - "addressee": "Arthur Dent", - "line1": "20 W 34th St", - "line2": "Empire State Building", - "city": "New York", - "state": "New York", - "country": "US", - "postalCode": "10118", - }, - "shippingProvider": "Shipping Company, Co.", - "shippingTracking": "tr00000000001", - "shippingTrackingURL": "https://www.shippingcompany.com/tracking/tr00000000001", - "customerInfo": {"fullName": "Arthur Dent", "email": "arthur.dent@example.com"}, - "purchasedItems": [ - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "productId": "66072fb61b89448912e26791", - "productName": "Luxurious Fresh Ball", - "productSlug": "luxurious-fresh-ball", - "variantId": "66072fb71b89448912e2683f", - "variantName": "Luxurious Fresh Ball Generic: Bronze, Practical: Plastic", - "variantSlug": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantSKU": "luxurious-fresh-ball-generic-bronze-practical-plastic", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2672c_image14.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 55.61 USD"}, - "weight": 11, - "width": 82, - "height": 70, - "length": 9, - }, - { - "count": 1, - "rowTotal": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "productId": "66072fb61b89448912e26799", - "productName": "Recycled Steel Gloves", - "productSlug": "recycled-steel-gloves", - "variantId": "66072fb91b89448912e26ab9", - "variantName": "Recycled Steel Gloves Electronic: Granite, Handcrafted: grey", - "variantSlug": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantSKU": "recycled-steel-gloves-electronic-granite-handcrafted-grey", - "variantImage": { - "url": "https://dev-assets.website-files.com/66072f39417a2a35b2589cc7/66072fb51b89448912e2671e_image2.jpeg" - }, - "variantPrice": {"unit": "USD", "value": "5892", "string": "$ 53.44 USD"}, - "weight": 38, - "width": 76, - "height": 85, - "length": 40, - }, - ], - "purchasedItemsCount": 2, - "stripeDetails": { - "subscriptionId": "sub_1J6xwG2eZvKYlo2CXu9Zt0Tn", - "paymentMethod": "pm_1OzmzBJYFi4lcbXWHKNdXU7j", - "paymentIntentId": "pi_3OzmzDJYFi4lcbXW1hTBW6ft", - "customerId": "cus_PpRsNHwWdUoRKR", - "chargeId": "ch_3OzmzDJYFi4lcbXW1ndkkrH2", - "disputeId": "disputeId", - "refundId": "re_3OzmzDJYFi4lcbXW1kFAmlBk", - "refundReason": "fraudulent", - }, - "stripeCard": { - "last4": "4242", - "brand": "Visa", - "ownerName": "Arthur Dent", - "expires": {"year": 2024, "month": 4}, - }, - "paypalDetails": { - "orderId": "1a2b3c4d5e6f7g8h9i0j", - "payerId": "9k8j7i6h5g4f3e2d1c0b", - "captureId": "qwe123rty456uio789p", - "refundId": "abcde12345fghij67890", - "refundReason": "Customer requested refund", - "disputeId": "zxcvbnm987poiuytrewq", - }, - "customData": [{"key": "value"}], - "metadata": {"isBuyNow": False}, - "isCustomerDeleted": False, - "isShippingRequired": True, - "hasDownloads": False, - "paymentProcessor": "stripe", - "totals": { - "subtotal": {"unit": "USD", "value": "5892", "string": "$ 109.05 USD"}, - "extras": [ - { - "type": "tax", - "name": "State Taxes", - "description": "NY Taxes (4.00%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 4.36 USD"}, - }, - { - "type": "tax", - "name": "City Taxes", - "description": "NEW YORK Taxes (4.88%)", - "price": {"unit": "USD", "value": "5892", "string": "$ 5.32 USD"}, - }, - { - "type": "shipping", - "name": "Flat", - "description": "", - "price": {"unit": "USD", "value": "5892", "string": "$ 0.00 USD"}, - }, - ], - "total": {"unit": "USD", "value": "5892", "string": "$ 118.73 USD"}, - }, - "downloadFiles": [ - { - "id": "5e9a5eba75e0ac242e1b6f64", - "name": "New product guide", - "url": "https://webflow.com/dashboard/download-digital-product?payload=5d93ba5e38c6b0160ab711d3;e7634a;5eb1aac72912ec06f561278c;5e9a5eba75e0ac242e1b6f63:ka2nehxy:4a1ee0a632feaab94294350087215ed89533f2f530903e3b933b638940e921aa", - } - ], - } - expected_types: typing.Any = { - "orderId": None, - "status": None, - "comment": None, - "orderComment": None, - "acceptedOn": "datetime", - "fulfilledOn": "datetime", - "refundedOn": "datetime", - "disputedOn": "datetime", - "disputeUpdatedOn": "datetime", - "disputeLastStatus": None, - "customerPaid": {"unit": None, "value": None, "string": None}, - "netAmount": {"unit": None, "value": None, "string": None}, - "applicationFee": {"unit": None, "value": None, "string": None}, - "allAddresses": ( - "list", - { - 0: { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - 1: { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - }, - ), - "shippingAddress": { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "billingAddress": { - "type": None, - "japanType": None, - "addressee": None, - "line1": None, - "line2": None, - "city": None, - "state": None, - "country": None, - "postalCode": None, - }, - "shippingProvider": None, - "shippingTracking": None, - "shippingTrackingURL": None, - "customerInfo": {"fullName": None, "email": None}, - "purchasedItems": ( - "list", - { - 0: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - 1: { - "count": None, - "rowTotal": {"unit": None, "value": None, "string": None}, - "productId": None, - "productName": None, - "productSlug": None, - "variantId": None, - "variantName": None, - "variantSlug": None, - "variantSKU": None, - "variantImage": {"url": None}, - "variantPrice": {"unit": None, "value": None, "string": None}, - "weight": None, - "width": None, - "height": None, - "length": None, - }, - }, - ), - "purchasedItemsCount": None, - "stripeDetails": { - "subscriptionId": None, - "paymentMethod": None, - "paymentIntentId": None, - "customerId": None, - "chargeId": None, - "disputeId": None, - "refundId": None, - "refundReason": None, - }, - "stripeCard": {"last4": None, "brand": None, "ownerName": None, "expires": {"year": None, "month": None}}, - "paypalDetails": { - "orderId": None, - "payerId": None, - "captureId": None, - "refundId": None, - "refundReason": None, - "disputeId": None, - }, - "customData": ("list", {0: ("dict", {0: (None, None)})}), - "metadata": {"isBuyNow": None}, - "isCustomerDeleted": None, - "isShippingRequired": None, - "hasDownloads": None, - "paymentProcessor": None, - "totals": { - "subtotal": {"unit": None, "value": None, "string": None}, - "extras": ( - "list", - { - 0: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 1: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - 2: { - "type": None, - "name": None, - "description": None, - "price": {"unit": None, "value": None, "string": None}, - }, - }, - ), - "total": {"unit": None, "value": None, "string": None}, - }, - "downloadFiles": ("list", {0: {"id": None, "name": None, "url": None}}), - } - response = client.orders.refund(site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.orders.refund( - site_id="580e63e98c9a982ac9b8b741", order_id="5e8518516e147040726cc415" - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_pages.py b/tests/test_pages.py deleted file mode 100644 index 63003be..0000000 --- a/tests/test_pages.py +++ /dev/null @@ -1,407 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response -from webflow.resources.pages import PageMetadataWriteSeo -from webflow.resources.pages import PageMetadataWriteOpenGraph -from webflow import TextNodeWrite -from webflow import Select -from webflow import SelectNodeWriteChoicesItem -from webflow import TextInputNodeWrite -from webflow import SubmitButtonNodeWrite -from webflow import ComponentInstanceNodePropertyOverridesWrite -from webflow import ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "pages": [ - { - "id": "6596da6045e56dee495bcbba", - "siteId": "6258612d1ee792848f805dcf", - "title": "Guide to the Galaxy", - "slug": "guide-to-the-galaxy", - "parentId": "6419db964a9c435aa3af6251", - "collectionId": "6390c49774a71f12831a08e3", - "createdOn": "2024-03-11T10:42:00Z", - "lastUpdated": "2024-03-11T10:42:42Z", - "archived": False, - "draft": False, - "canBranch": False, - "isBranch": True, - "branchId": "68026fa68ef6dc744c75b833", - "seo": { - "title": "The Ultimate Hitchhiker's Guide to the Galaxy", - "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", - }, - "openGraph": { - "title": "Explore the Cosmos with The Ultimate Guide", - "titleCopied": False, - "description": "Dive deep into the mysteries of the universe with your guide to everything galactic.", - "descriptionCopied": False, - }, - "localeId": "653fd9af6a07fc9cfd7a5e57", - "publishedPath": "/en-us/guide-to-the-galaxy", - }, - { - "id": "6596da6045e56dee495bcbad", - "siteId": "6258612d1ee792848f805dcf", - "title": "Towel Day Celebrations", - "slug": "towel-day", - "parentId": "6419db964a9c435aa3af6251", - "collectionId": "6390c49774a71f12831a08e3", - "createdOn": "2024-05-25T09:00:00Z", - "lastUpdated": "2024-05-25T09:42:00Z", - "archived": False, - "draft": False, - "canBranch": True, - "isBranch": False, - "branchId": "68026fa68ef6dc744c75b833", - "seo": { - "title": "Celebrate Towel Day - The Hitchhiker's Guide to the Galaxy", - "description": "A guide to celebrating Towel Day, in honor of the most massively useful thing an interstellar hitchhiker can have.", - }, - "openGraph": { - "title": "Towel Day - Don't Panic", - "titleCopied": False, - "description": "Join the galaxy in celebrating Towel Day, the day dedicated to carrying towels everywhere in memory of Douglas Adams.", - "descriptionCopied": False, - }, - "localeId": "653fd9af6a07fc9cfd7a5e57", - "publishedPath": "/en-us/towel-day", - }, - ], - "pagination": {"limit": 20, "offset": 0, "total": 2}, - } - expected_types: typing.Any = { - "pages": ( - "list", - { - 0: { - "id": None, - "siteId": None, - "title": None, - "slug": None, - "parentId": None, - "collectionId": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - "archived": None, - "draft": None, - "canBranch": None, - "isBranch": None, - "branchId": None, - "seo": {"title": None, "description": None}, - "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, - "localeId": None, - "publishedPath": None, - }, - 1: { - "id": None, - "siteId": None, - "title": None, - "slug": None, - "parentId": None, - "collectionId": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - "archived": None, - "draft": None, - "canBranch": None, - "isBranch": None, - "branchId": None, - "seo": {"title": None, "description": None}, - "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, - "localeId": None, - "publishedPath": None, - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.pages.list( - site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0", limit=1, offset=1 - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.pages.list( - site_id="580e63e98c9a982ac9b8b741", locale_id="65427cf400e02b306eaa04a0", limit=1, offset=1 - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get_metadata(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "6596da6045e56dee495bcbba", - "siteId": "6258612d1ee792848f805dcf", - "title": "Guide to the Galaxy", - "slug": "guide-to-the-galaxy", - "parentId": "6419db964a9c435aa3af6251", - "collectionId": "6390c49774a71f12831a08e3", - "createdOn": "2024-03-11T10:42:00Z", - "lastUpdated": "2024-03-11T10:42:42Z", - "archived": False, - "draft": False, - "canBranch": False, - "isBranch": True, - "branchId": "68026fa68ef6dc744c75b833", - "seo": { - "title": "The Ultimate Hitchhiker's Guide to the Galaxy", - "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", - }, - "openGraph": { - "title": "Explore the Cosmos with The Ultimate Guide", - "titleCopied": False, - "description": "Dive deep into the mysteries of the universe with your guide to everything galactic.", - "descriptionCopied": False, - }, - "localeId": "653fd9af6a07fc9cfd7a5e57", - "publishedPath": "/en-us/guide-to-the-galaxy", - } - expected_types: typing.Any = { - "id": None, - "siteId": None, - "title": None, - "slug": None, - "parentId": None, - "collectionId": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - "archived": None, - "draft": None, - "canBranch": None, - "isBranch": None, - "branchId": None, - "seo": {"title": None, "description": None}, - "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, - "localeId": None, - "publishedPath": None, - } - response = client.pages.get_metadata(page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.pages.get_metadata( - page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_update_page_settings(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "6596da6045e56dee495bcbba", - "siteId": "6258612d1ee792848f805dcf", - "title": "Guide to the Galaxy", - "slug": "guide-to-the-galaxy", - "parentId": "6419db964a9c435aa3af6251", - "collectionId": "6390c49774a71f12831a08e3", - "createdOn": "2024-03-11T10:42:00Z", - "lastUpdated": "2024-03-11T10:42:42Z", - "archived": False, - "draft": False, - "canBranch": False, - "isBranch": True, - "branchId": "68026fa68ef6dc744c75b833", - "seo": { - "title": "The Ultimate Hitchhiker's Guide to the Galaxy", - "description": "Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", - }, - "openGraph": { - "title": "Explore the Cosmos with The Ultimate Guide", - "titleCopied": False, - "description": "Dive deep into the mysteries of the universe with your guide to everything galactic.", - "descriptionCopied": False, - }, - "localeId": "653fd9af6a07fc9cfd7a5e57", - "publishedPath": "/en-us/guide-to-the-galaxy", - } - expected_types: typing.Any = { - "id": None, - "siteId": None, - "title": None, - "slug": None, - "parentId": None, - "collectionId": None, - "createdOn": "datetime", - "lastUpdated": "datetime", - "archived": None, - "draft": None, - "canBranch": None, - "isBranch": None, - "branchId": None, - "seo": {"title": None, "description": None}, - "openGraph": {"title": None, "titleCopied": None, "description": None, "descriptionCopied": None}, - "localeId": None, - "publishedPath": None, - } - response = client.pages.update_page_settings( - page_id="63c720f9347c2139b248e552", - locale_id="65427cf400e02b306eaa04a0", - title="Guide to the Galaxy", - slug="guide-to-the-galaxy", - seo=PageMetadataWriteSeo( - title="The Ultimate Hitchhiker's Guide to the Galaxy", - description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", - ), - open_graph=PageMetadataWriteOpenGraph( - title="Explore the Cosmos with The Ultimate Guide", - title_copied=False, - description="Dive deep into the mysteries of the universe with your guide to everything galactic.", - description_copied=False, - ), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.pages.update_page_settings( - page_id="63c720f9347c2139b248e552", - locale_id="65427cf400e02b306eaa04a0", - title="Guide to the Galaxy", - slug="guide-to-the-galaxy", - seo=PageMetadataWriteSeo( - title="The Ultimate Hitchhiker's Guide to the Galaxy", - description="Everything you need to know about the galaxy, from avoiding Vogon poetry to the importance of towels.", - ), - open_graph=PageMetadataWriteOpenGraph( - title="Explore the Cosmos with The Ultimate Guide", - title_copied=False, - description="Dive deep into the mysteries of the universe with your guide to everything galactic.", - description_copied=False, - ), - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get_content(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "pageId": "658205daa3e8206a523b5ad4", - "branchId": "68026fa68ef6dc744c75b833", - "nodes": [ - {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, - {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, - {"id": "id", "image": {}, "attributes": {"key": "value"}, "type": "image"}, - { - "id": "id", - "choices": [{"value": "value", "text": "text"}], - "attributes": {"key": "value"}, - "type": "select", - }, - {"id": "id", "placeholder": "placeholder", "attributes": {"key": "value"}, "type": "text-input"}, - {"id": "id", "text": {}, "attributes": {"key": "value"}, "type": "text"}, - { - "id": "id", - "componentId": "componentId", - "propertyOverrides": [{"propertyId": "7dd14c08-2e96-8d3d-2b19-b5c03642a0f0"}], - "type": "component-instance", - }, - ], - "pagination": {"limit": 4, "offset": 0, "total": 4}, - "lastUpdated": "2016-10-24T19:42:38Z", - } - expected_types: typing.Any = { - "pageId": None, - "branchId": None, - "nodes": ( - "list", - { - 0: "no_validate", - 1: "no_validate", - 2: "no_validate", - 3: "no_validate", - 4: "no_validate", - 5: "no_validate", - 6: "no_validate", - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - "lastUpdated": "datetime", - } - response = client.pages.get_content( - page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", limit=1, offset=1 - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.pages.get_content( - page_id="63c720f9347c2139b248e552", locale_id="65427cf400e02b306eaa04a0", limit=1, offset=1 - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_update_static_content(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = {"errors": ["errors"]} - expected_types: typing.Any = {"errors": ("list", {0: None})} - response = client.pages.update_static_content( - page_id="63c720f9347c2139b248e552", - locale_id="localeId", - nodes=[ - TextNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

" - ), - TextNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", - text="

Don't Panic!

Always know where your towel is.

", - ), - Select( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", - choices=[ - SelectNodeWriteChoicesItem(value="choice-1", text="First choice"), - SelectNodeWriteChoicesItem(value="choice-2", text="Second choice"), - ], - ), - TextInputNodeWrite(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", placeholder="Enter something here..."), - SubmitButtonNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", value="Submit", waiting_text="Submitting..." - ), - ComponentInstanceNodePropertyOverridesWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", - property_overrides=[ - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", - text="

Time is an illusion

", - ), - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", text="Life, the Universe and Everything" - ), - ], - ), - ], - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.pages.update_static_content( - page_id="63c720f9347c2139b248e552", - locale_id="localeId", - nodes=[ - TextNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad623", text="

The Hitchhiker's Guide to the Galaxy

" - ), - TextNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad627", - text="

Don't Panic!

Always know where your towel is.

", - ), - Select( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad635", - choices=[ - SelectNodeWriteChoicesItem(value="choice-1", text="First choice"), - SelectNodeWriteChoicesItem(value="choice-2", text="Second choice"), - ], - ), - TextInputNodeWrite(node_id="a245c12d-995b-55ee-5ec7-aa36a6cad642", placeholder="Enter something here..."), - SubmitButtonNodeWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad671", value="Submit", waiting_text="Submitting..." - ), - ComponentInstanceNodePropertyOverridesWrite( - node_id="a245c12d-995b-55ee-5ec7-aa36a6cad629", - property_overrides=[ - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f0", - text="

Time is an illusion

", - ), - ComponentInstanceNodePropertyOverridesWritePropertyOverridesItem( - property_id="7dd14c08-2e96-8d3d-2b19-b5c03642a0f1", text="Life, the Universe and Everything" - ), - ], - ), - ], - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_products.py b/tests/test_products.py deleted file mode 100644 index 3438763..0000000 --- a/tests/test_products.py +++ /dev/null @@ -1,700 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response -from webflow.resources.products import ProductSkuCreateProduct -from webflow import ProductFieldData -from webflow import SkuPropertyList -from webflow import SkuPropertyListEnumItem -from webflow.resources.products import ProductSkuCreateSku -from webflow import SkuFieldData -from webflow import SkuFieldDataPrice -from webflow import Sku -import datetime - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "items": [ - { - "product": { - "id": "660eb7a486d1d6e0412292d7", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2024-04-04T14:24:19Z", - "lastUpdated": "2024-04-04T14:30:19Z", - "createdOn": "2024-04-04T14:22:28Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "T-Shirt", - "slug": "t-shirt", - "description": "A plain cotton t-shirt.", - "shippable": True, - "sku-properties": [ - { - "id": "Color", - "name": "Color", - "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], - } - ], - }, - }, - "skus": [ - { - "id": "66072fb71b89448912e2681c", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2023-03-17T18:47:35Z", - "lastUpdated": "2023-03-17T18:47:35Z", - "createdOn": "2023-03-17T18:47:35Z", - "fieldData": { - "sku-values": {"color": "blue", "size": "small"}, - "name": "Colorful T-shirt - Default", - "slug": "colorful-t-shirt-default", - "price": {"value": 2499, "unit": "USD", "currency": "USD"}, - "main-image": "https://www.example.com/image.jpg", - "sku": "1234567890", - "sku-properties": [ - { - "id": "Color", - "name": "Color", - "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], - } - ], - }, - } - ], - } - ], - "pagination": {"limit": 100, "offset": 0, "total": 100}, - } - expected_types: typing.Any = { - "items": ( - "list", - { - 0: { - "product": { - "id": None, - "cmsLocaleId": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "createdOn": "datetime", - "isArchived": None, - "isDraft": None, - "fieldData": { - "name": None, - "slug": None, - "description": None, - "shippable": None, - "sku-properties": ( - "list", - { - 0: { - "id": None, - "name": None, - "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), - } - }, - ), - }, - }, - "skus": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "createdOn": "datetime", - "fieldData": { - "sku-values": ("dict", {0: (None, None), 1: (None, None)}), - "name": None, - "slug": None, - "price": {"value": None, "unit": None, "currency": None}, - "main-image": None, - "sku": None, - "sku-properties": ( - "list", - { - 0: { - "id": None, - "name": None, - "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), - } - }, - ), - }, - } - }, - ), - } - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.products.list(site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.products.list(site_id="580e63e98c9a982ac9b8b741", offset=1, limit=1) - validate_response(async_response, expected_response, expected_types) - - -async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "product": { - "id": "660eb7a486d1d6e0412292d7", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2024-04-04T14:24:19Z", - "lastUpdated": "2024-04-04T14:30:19Z", - "createdOn": "2024-04-04T14:22:28Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "T-Shirt", - "slug": "t-shirt", - "description": "A plain cotton t-shirt.", - "shippable": True, - "sku-properties": [ - { - "id": "Color", - "name": "Color", - "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], - } - ], - "category": ["category"], - "tax-category": "standard-taxable", - "default-sku": "default-sku", - "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", - }, - }, - "skus": [ - { - "id": "66072fb71b89448912e2681c", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2023-03-17T18:47:35Z", - "lastUpdated": "2023-03-17T18:47:35Z", - "createdOn": "2023-03-17T18:47:35Z", - "fieldData": { - "sku-values": {"color": "blue", "size": "small"}, - "name": "Colorful T-shirt - Default", - "slug": "colorful-t-shirt-default", - "price": {"value": 2499, "unit": "USD", "currency": "USD"}, - "main-image": "https://www.example.com/image.jpg", - "sku": "1234567890", - "sku-properties": [ - { - "id": "Color", - "name": "Color", - "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], - } - ], - }, - } - ], - } - expected_types: typing.Any = { - "product": { - "id": None, - "cmsLocaleId": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "createdOn": "datetime", - "isArchived": None, - "isDraft": None, - "fieldData": { - "name": None, - "slug": None, - "description": None, - "shippable": None, - "sku-properties": ( - "list", - {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, - ), - "category": ("list", {0: None}), - "tax-category": None, - "default-sku": None, - "ec-product-type": None, - }, - }, - "skus": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "createdOn": "datetime", - "fieldData": { - "sku-values": ("dict", {0: (None, None), 1: (None, None)}), - "name": None, - "slug": None, - "price": {"value": None, "unit": None, "currency": None}, - "main-image": None, - "sku": None, - "sku-properties": ( - "list", - { - 0: { - "id": None, - "name": None, - "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), - } - }, - ), - }, - } - }, - ), - } - response = client.products.create( - site_id="580e63e98c9a982ac9b8b741", - publish_status="staging", - product=ProductSkuCreateProduct( - field_data=ProductFieldData( - name="Colorful T-shirt", - slug="colorful-t-shirt", - description="Our best-selling t-shirt available in multiple colors and sizes", - sku_properties=[ - SkuPropertyList( - id="color", - name="Color", - enum=[ - SkuPropertyListEnumItem(id="red", name="Red", slug="red"), - SkuPropertyListEnumItem(id="yellow", name="Yellow", slug="yellow"), - SkuPropertyListEnumItem(id="blue", name="Blue", slug="blue"), - ], - ), - SkuPropertyList( - id="size", - name="Size", - enum=[ - SkuPropertyListEnumItem(id="small", name="Small", slug="small"), - SkuPropertyListEnumItem(id="medium", name="Medium", slug="medium"), - SkuPropertyListEnumItem(id="large", name="Large", slug="large"), - ], - ), - ], - ) - ), - sku=ProductSkuCreateSku( - field_data=SkuFieldData( - name="Colorful T-shirt - Red Small", - slug="colorful-t-shirt-red-small", - price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), - main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", - ) - ), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.products.create( - site_id="580e63e98c9a982ac9b8b741", - publish_status="staging", - product=ProductSkuCreateProduct( - field_data=ProductFieldData( - name="Colorful T-shirt", - slug="colorful-t-shirt", - description="Our best-selling t-shirt available in multiple colors and sizes", - sku_properties=[ - SkuPropertyList( - id="color", - name="Color", - enum=[ - SkuPropertyListEnumItem(id="red", name="Red", slug="red"), - SkuPropertyListEnumItem(id="yellow", name="Yellow", slug="yellow"), - SkuPropertyListEnumItem(id="blue", name="Blue", slug="blue"), - ], - ), - SkuPropertyList( - id="size", - name="Size", - enum=[ - SkuPropertyListEnumItem(id="small", name="Small", slug="small"), - SkuPropertyListEnumItem(id="medium", name="Medium", slug="medium"), - SkuPropertyListEnumItem(id="large", name="Large", slug="large"), - ], - ), - ], - ) - ), - sku=ProductSkuCreateSku( - field_data=SkuFieldData( - name="Colorful T-shirt - Red Small", - slug="colorful-t-shirt-red-small", - price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), - main_image="https://rocketamp-sample-store.myshopify.com/cdn/shop/products/Gildan_2000_Antique_Cherry_Red_Front_1024x1024.jpg?v=1527232987", - ) - ), - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "product": { - "id": "660eb7a486d1d6e0412292d7", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2024-04-04T14:24:19Z", - "lastUpdated": "2024-04-04T14:30:19Z", - "createdOn": "2024-04-04T14:22:28Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "T-Shirt", - "slug": "t-shirt", - "description": "A plain cotton t-shirt.", - "shippable": True, - "sku-properties": [ - { - "id": "Color", - "name": "Color", - "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], - } - ], - "category": ["category"], - "tax-category": "standard-taxable", - "default-sku": "default-sku", - "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", - }, - }, - "skus": [ - { - "id": "66072fb71b89448912e2681c", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2023-03-17T18:47:35Z", - "lastUpdated": "2023-03-17T18:47:35Z", - "createdOn": "2023-03-17T18:47:35Z", - "fieldData": { - "sku-values": {"color": "blue", "size": "small"}, - "name": "Colorful T-shirt - Default", - "slug": "colorful-t-shirt-default", - "price": {"value": 2499, "unit": "USD", "currency": "USD"}, - "main-image": "https://www.example.com/image.jpg", - "sku": "1234567890", - "sku-properties": [ - { - "id": "Color", - "name": "Color", - "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], - } - ], - }, - } - ], - } - expected_types: typing.Any = { - "product": { - "id": None, - "cmsLocaleId": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "createdOn": "datetime", - "isArchived": None, - "isDraft": None, - "fieldData": { - "name": None, - "slug": None, - "description": None, - "shippable": None, - "sku-properties": ( - "list", - {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, - ), - "category": ("list", {0: None}), - "tax-category": None, - "default-sku": None, - "ec-product-type": None, - }, - }, - "skus": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "createdOn": "datetime", - "fieldData": { - "sku-values": ("dict", {0: (None, None), 1: (None, None)}), - "name": None, - "slug": None, - "price": {"value": None, "unit": None, "currency": None}, - "main-image": None, - "sku": None, - "sku-properties": ( - "list", - { - 0: { - "id": None, - "name": None, - "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), - } - }, - ), - }, - } - }, - ), - } - response = client.products.get(site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.products.get( - site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "660eb7a486d1d6e0412292d7", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2024-04-04T14:24:19Z", - "lastUpdated": "2024-04-04T14:30:19Z", - "createdOn": "2024-04-04T14:22:28Z", - "isArchived": False, - "isDraft": False, - "fieldData": { - "name": "T-Shirt", - "slug": "t-shirt", - "description": "A plain cotton t-shirt.", - "shippable": True, - "sku-properties": [ - { - "id": "Color", - "name": "Color", - "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], - } - ], - "category": ["category"], - "tax-category": "standard-taxable", - "default-sku": "default-sku", - "ec-product-type": "ff42fee0113744f693a764e3431a9cc2", - }, - } - expected_types: typing.Any = { - "id": None, - "cmsLocaleId": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "createdOn": "datetime", - "isArchived": None, - "isDraft": None, - "fieldData": { - "name": None, - "slug": None, - "description": None, - "shippable": None, - "sku-properties": ( - "list", - {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, - ), - "category": ("list", {0: None}), - "tax-category": None, - "default-sku": None, - "ec-product-type": None, - }, - } - response = client.products.update(site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.products.update( - site_id="580e63e98c9a982ac9b8b741", product_id="580e63fc8c9a982ac9b8b745" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_create_sku(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "skus": [ - { - "id": "66072fb71b89448912e2681c", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2023-03-17T18:47:35Z", - "lastUpdated": "2023-03-17T18:47:35Z", - "createdOn": "2023-03-17T18:47:35Z", - "fieldData": { - "sku-values": {"color": "blue", "size": "small"}, - "name": "Colorful T-shirt - Default", - "slug": "colorful-t-shirt-default", - "price": {"value": 2499, "unit": "USD", "currency": "USD"}, - "main-image": "https://www.example.com/image.jpg", - "sku": "1234567890", - "sku-properties": [ - { - "id": "Color", - "name": "Color", - "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], - } - ], - }, - } - ] - } - expected_types: typing.Any = { - "skus": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "createdOn": "datetime", - "fieldData": { - "sku-values": ("dict", {0: (None, None), 1: (None, None)}), - "name": None, - "slug": None, - "price": {"value": None, "unit": None, "currency": None}, - "main-image": None, - "sku": None, - "sku-properties": ( - "list", - { - 0: { - "id": None, - "name": None, - "enum": ("list", {0: {"id": None, "name": None, "slug": None}}), - } - }, - ), - }, - } - }, - ) - } - response = client.products.create_sku( - site_id="580e63e98c9a982ac9b8b741", - product_id="580e63fc8c9a982ac9b8b745", - skus=[ - Sku( - id="66072fb71b89448912e2681c", - cms_locale_id="653ad57de882f528b32e810e", - last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - field_data=SkuFieldData( - name="Colorful T-shirt - Default", - slug="colorful-t-shirt-default", - price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), - ), - ) - ], - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.products.create_sku( - site_id="580e63e98c9a982ac9b8b741", - product_id="580e63fc8c9a982ac9b8b745", - skus=[ - Sku( - id="66072fb71b89448912e2681c", - cms_locale_id="653ad57de882f528b32e810e", - last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - field_data=SkuFieldData( - name="Colorful T-shirt - Default", - slug="colorful-t-shirt-default", - price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), - ), - ) - ], - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_update_sku(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "66072fb71b89448912e2681c", - "cmsLocaleId": "653ad57de882f528b32e810e", - "lastPublished": "2023-03-17T18:47:35Z", - "lastUpdated": "2023-03-17T18:47:35Z", - "createdOn": "2023-03-17T18:47:35Z", - "fieldData": { - "sku-values": {"color": "blue", "size": "small"}, - "name": "Colorful T-shirt - Default", - "slug": "colorful-t-shirt-default", - "price": {"value": 2499, "unit": "USD", "currency": "USD"}, - "compare-at-price": {"value": 100, "unit": "USD"}, - "ec-sku-billing-method": "one-time", - "ec-sku-subscription-plan": {"interval": "day", "frequency": 1, "trial": 7, "plans": [{}]}, - "main-image": "https://www.example.com/image.jpg", - "sku": "1234567890", - "sku-properties": [ - { - "id": "Color", - "name": "Color", - "enum": [{"id": "royal-blue", "name": "Royal Blue", "slug": "royal-blue"}], - } - ], - }, - } - expected_types: typing.Any = { - "id": None, - "cmsLocaleId": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "createdOn": "datetime", - "fieldData": { - "sku-values": ("dict", {0: (None, None), 1: (None, None)}), - "name": None, - "slug": None, - "price": {"value": None, "unit": None, "currency": None}, - "compare-at-price": {"value": None, "unit": None}, - "ec-sku-billing-method": None, - "ec-sku-subscription-plan": { - "interval": None, - "frequency": None, - "trial": None, - "plans": ("list", {0: {}}), - }, - "main-image": None, - "sku": None, - "sku-properties": ( - "list", - {0: {"id": None, "name": None, "enum": ("list", {0: {"id": None, "name": None, "slug": None}})}}, - ), - }, - } - response = client.products.update_sku( - site_id="580e63e98c9a982ac9b8b741", - product_id="580e63fc8c9a982ac9b8b745", - sku_id="5e8518516e147040726cc415", - sku=Sku( - id="66072fb71b89448912e2681c", - cms_locale_id="653ad57de882f528b32e810e", - last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - field_data=SkuFieldData( - name="Colorful T-shirt - Default", - slug="colorful-t-shirt-default", - price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), - ), - ), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.products.update_sku( - site_id="580e63e98c9a982ac9b8b741", - product_id="580e63fc8c9a982ac9b8b745", - sku_id="5e8518516e147040726cc415", - sku=Sku( - id="66072fb71b89448912e2681c", - cms_locale_id="653ad57de882f528b32e810e", - last_published=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - last_updated=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - created_on=datetime.datetime.fromisoformat("2023-03-17 18:47:35+00:00"), - field_data=SkuFieldData( - name="Colorful T-shirt - Default", - slug="colorful-t-shirt-default", - price=SkuFieldDataPrice(value=2499.0, unit="USD", currency="USD"), - ), - ), - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_scripts.py b/tests/test_scripts.py deleted file mode 100644 index f81f7fc..0000000 --- a/tests/test_scripts.py +++ /dev/null @@ -1,159 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "registeredScripts": [ - { - "id": "alert", - "canCopy": False, - "displayName": "Alert", - "hostedLocation": "https://cdn.webflow.io/.../alert-0.0.1.js", - "integrityHash": "integrityHash", - "createdOn": "2022-10-26T00:28:54.191Z", - "lastUpdated": "lastUpdated", - "version": "0.0.1", - }, - { - "id": "alert", - "canCopy": False, - "displayName": "Alert", - "hostedLocation": "https://cdn.webflow.io/.../alert-0.0.2.js", - "integrityHash": "integrityHash", - "createdOn": "2022-10-26T00:28:54.191Z", - "lastUpdated": "lastUpdated", - "version": "0.0.2", - }, - { - "id": "cms_slider", - "canCopy": True, - "displayName": "CMS Slider", - "hostedLocation": "https://cdn.jsdelivr.net/.../cms_slider.js", - "integrityHash": "sha384-J+YlJ8v0gpaRoKH7SbFbEmxOZlAxLiwNjfSsBhDooGa5roXlPPpXbEevck4J7YZ+", - "createdOn": "2022-10-26T00:28:54.191Z", - "lastUpdated": "lastUpdated", - "version": "1.0.0", - }, - ], - "pagination": {"limit": 100, "offset": 0, "total": 3}, - } - expected_types: typing.Any = { - "registeredScripts": ( - "list", - { - 0: { - "id": None, - "canCopy": None, - "displayName": None, - "hostedLocation": None, - "integrityHash": None, - "createdOn": None, - "lastUpdated": None, - "version": None, - }, - 1: { - "id": None, - "canCopy": None, - "displayName": None, - "hostedLocation": None, - "integrityHash": None, - "createdOn": None, - "lastUpdated": None, - "version": None, - }, - 2: { - "id": None, - "canCopy": None, - "displayName": None, - "hostedLocation": None, - "integrityHash": None, - "createdOn": None, - "lastUpdated": None, - "version": None, - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.scripts.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.scripts.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_register_hosted(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "cms_slider", - "canCopy": True, - "displayName": "CMS Slider", - "hostedLocation": "https://cdn.jsdelivr.net/.../cmsslider.js", - "integrityHash": "sha384-J+YlJ8v0gpaRoKH7SbFbEmxOZlAxLiwNjfSsBhDooGa5roXlPPpXbEevck4J7YZ+", - "createdOn": "2022-10-26T00:28:54.191Z", - "lastUpdated": "lastUpdated", - "version": "1.0.0", - } - expected_types: typing.Any = { - "id": None, - "canCopy": None, - "displayName": None, - "hostedLocation": None, - "integrityHash": None, - "createdOn": None, - "lastUpdated": None, - "version": None, - } - response = client.scripts.register_hosted( - site_id="580e63e98c9a982ac9b8b741", - hosted_location="hostedLocation", - integrity_hash="integrityHash", - version="version", - display_name="displayName", - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.scripts.register_hosted( - site_id="580e63e98c9a982ac9b8b741", - hosted_location="hostedLocation", - integrity_hash="integrityHash", - version="version", - display_name="displayName", - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_register_inline(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "alert", - "canCopy": False, - "displayName": "Alert", - "hostedLocation": "https://uploads-ssl.webflow.com/6258612d1ee792848f805dcf%2F64b6c769ff52ba6c3d904a91%2F660d6e15b3d1696f2d2b1447%2Falert-0.0.1.js", - "integrityHash": "integrityHash", - "createdOn": "2022-10-26T00:28:54.191Z", - "lastUpdated": "lastUpdated", - "version": "0.0.1", - } - expected_types: typing.Any = { - "id": None, - "canCopy": None, - "displayName": None, - "hostedLocation": None, - "integrityHash": None, - "createdOn": None, - "lastUpdated": None, - "version": None, - } - response = client.scripts.register_inline( - site_id="580e63e98c9a982ac9b8b741", source_code="alert('hello world');", version="0.0.1", display_name="Alert" - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.scripts.register_inline( - site_id="580e63e98c9a982ac9b8b741", source_code="alert('hello world');", version="0.0.1", display_name="Alert" - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_sites.py b/tests/test_sites.py deleted file mode 100644 index d1fc7bc..0000000 --- a/tests/test_sites.py +++ /dev/null @@ -1,645 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response - - -async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "670ecf86817e3cc7a510eb6a", - "workspaceId": "625860a7a6c16d624927122f", - "createdOn": "2024-10-15T20:24:38Z", - "displayName": "The Hitchiker's Guide", - "shortName": "hitchikers-guide", - "lastPublished": "2016-10-24T19:43:17Z", - "lastUpdated": "2024-10-15T20:24:38Z", - "previewUrl": "https://dev-assets.website-files.com/580e63e98c9a982ac9b8b741/201610241243.png", - "timeZone": "America/Los_Angeles", - "parentFolderId": "670ece123598db72d9648be1", - "customDomains": [ - {"id": "589a331aa51e760df7ccb89d", "url": "test-api-domain.com", "lastPublished": "2022-12-07T16:51:37Z"} - ], - "locales": { - "primary": { - "id": "653fd9af6a07fc9cfd7a5e57", - "cmsLocaleId": "653ad57de882f528b32e810e", - "enabled": False, - "displayName": "English (United States)", - "displayImageId": "displayImageId", - "redirect": True, - "subdirectory": "", - "tag": "en-US", - }, - "secondary": [ - { - "id": "653fd9af6a07fc9cfd7a5e57", - "cmsLocaleId": "653ad57de882f528b32e810e", - "enabled": False, - "displayName": "English (United States)", - "redirect": True, - "subdirectory": "", - "tag": "en-US", - } - ], - }, - "dataCollectionEnabled": True, - "dataCollectionType": "always", - } - expected_types: typing.Any = { - "id": None, - "workspaceId": None, - "createdOn": "datetime", - "displayName": None, - "shortName": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "previewUrl": None, - "timeZone": None, - "parentFolderId": None, - "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), - "locales": { - "primary": { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "displayImageId": None, - "redirect": None, - "subdirectory": None, - "tag": None, - }, - "secondary": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "redirect": None, - "subdirectory": None, - "tag": None, - } - }, - ), - }, - "dataCollectionEnabled": None, - "dataCollectionType": None, - } - response = client.sites.create(workspace_id="580e63e98c9a982ac9b8b741", name="The Hitchhiker's Guide to the Galaxy") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.create( - workspace_id="580e63e98c9a982ac9b8b741", name="The Hitchhiker's Guide to the Galaxy" - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "sites": [ - { - "id": "42e63e98c9a982ac9b8b741", - "workspaceId": "42e63fc8c9a982ac9b8b744", - "createdOn": "1979-10-12T12:00:00Z", - "displayName": "Heart of Gold Spaceship", - "shortName": "heart-of-gold", - "lastPublished": "2023-04-02T12:42:00Z", - "lastUpdated": "2016-10-24T19:43:17Z", - "previewUrl": "https://dev-assets.website-files.com/42e63e98c9a982ac9b8b741/197910121200.png", - "timeZone": "DeepSpace/InfiniteImprobability", - "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", - "customDomains": [ - { - "id": "589a331aa51e760df7ccb89e", - "url": "heartofgold.galaxy", - "lastPublished": "2022-12-07T16:51:37Z", - } - ], - "locales": { - "primary": { - "id": "653fd9af6a07fc9cfd7a5e57", - "cmsLocaleId": "653ad57de882f528b32e810e", - "enabled": True, - "displayName": "English - Heart of Gold Standard", - "redirect": False, - "subdirectory": "/en", - "tag": "The Ultimate Answer", - }, - "secondary": [ - { - "id": "653fd9af6a07fc9cfd7a5e58", - "cmsLocaleId": "653ad57de882f528b32e810g", - "enabled": True, - "displayName": "Betelgeusian - Vogon Liaison", - "redirect": True, - "subdirectory": "/bet", - "tag": "Vogon", - }, - { - "id": "653fd9af6a07fc9cfd7a5e59", - "cmsLocaleId": "653ad57de882f528b32e810h", - "enabled": False, - "displayName": "Magrathean - Custom Planet Designs", - "redirect": True, - "subdirectory": "/mg", - "tag": "Magrathean", - }, - ], - }, - "dataCollectionEnabled": True, - "dataCollectionType": "always", - }, - { - "id": "42e63e98c9a982ac9b8b742", - "workspaceId": "42e63fc8c9a982ac9b8b745", - "createdOn": "1981-10-12T12:00:00Z", - "displayName": "Marvin's Personal Blog", - "shortName": "paranoid-android", - "lastPublished": "2023-04-02T12:45:00Z", - "lastUpdated": "2016-10-24T19:43:17Z", - "previewUrl": "https://dev-assets.website-files.com/42e63e98c9a982ac9b8b742/198110121200.png", - "timeZone": "DeepSpace/Depression", - "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", - "customDomains": [ - {"id": "589a331aa51e760df7ccb89f", "url": "marvin.blog", "lastPublished": "2022-12-07T16:51:37Z"} - ], - "locales": { - "primary": { - "id": "653fd9af6a07fc9cfd7a5e57", - "cmsLocaleId": "653ad57de882f528b32e810e", - "enabled": True, - "displayName": "English - Marvin's Musings", - "redirect": False, - "subdirectory": "/en", - "tag": "English", - }, - "secondary": [ - { - "id": "653fd9af6a07fc9cfd7a5e56", - "cmsLocaleId": "653ad57de882f528b32e810f", - "enabled": True, - "displayName": "Squornshellous - Mattress Speak", - "redirect": True, - "subdirectory": "/sr", - "tag": "Squornshellous", - } - ], - }, - "dataCollectionEnabled": True, - "dataCollectionType": "always", - }, - { - "id": "42e63e98c9a982ac9b8b743", - "workspaceId": "42e63fc8c9a982ac9b8b746", - "createdOn": "1982-10-12T12:00:00Z", - "displayName": "Vogon Poetry Archive", - "shortName": "vogon-poetry", - "lastPublished": "2023-04-02T12:50:00Z", - "lastUpdated": "2016-10-24T19:43:17Z", - "previewUrl": "https://dev-assets.website-files.com/42e63e98c9a982ac9b8b743/198210121200.png", - "timeZone": "Vogsphere/PoetryHall", - "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", - "customDomains": [ - { - "id": "589a331aa51e760df7ccb8a0", - "url": "vogonpoetry.galaxy", - "lastPublished": "2022-12-07T16:51:37Z", - } - ], - "locales": { - "primary": { - "id": "653fd9af6a07fc9cfd7a5e55", - "cmsLocaleId": "653ad57de882f528b32e810d", - "enabled": True, - "displayName": "English - Vogon Verse", - "redirect": False, - "subdirectory": "/en", - "tag": "Third Worst Poetry", - }, - "secondary": [ - { - "id": "653fd9af6a07fc9cfd7a5e54", - "cmsLocaleId": "653ad57de882f528b32e810c", - "enabled": True, - "displayName": "Galactic - Universal Language", - "redirect": True, - "subdirectory": "/gl", - "tag": "Pan-Galactic Gargle Blaster", - } - ], - }, - "dataCollectionEnabled": True, - "dataCollectionType": "always", - }, - ] - } - expected_types: typing.Any = { - "sites": ( - "list", - { - 0: { - "id": None, - "workspaceId": None, - "createdOn": "datetime", - "displayName": None, - "shortName": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "previewUrl": None, - "timeZone": None, - "parentFolderId": None, - "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), - "locales": { - "primary": { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "redirect": None, - "subdirectory": None, - "tag": None, - }, - "secondary": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "redirect": None, - "subdirectory": None, - "tag": None, - }, - 1: { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "redirect": None, - "subdirectory": None, - "tag": None, - }, - }, - ), - }, - "dataCollectionEnabled": None, - "dataCollectionType": None, - }, - 1: { - "id": None, - "workspaceId": None, - "createdOn": "datetime", - "displayName": None, - "shortName": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "previewUrl": None, - "timeZone": None, - "parentFolderId": None, - "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), - "locales": { - "primary": { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "redirect": None, - "subdirectory": None, - "tag": None, - }, - "secondary": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "redirect": None, - "subdirectory": None, - "tag": None, - } - }, - ), - }, - "dataCollectionEnabled": None, - "dataCollectionType": None, - }, - 2: { - "id": None, - "workspaceId": None, - "createdOn": "datetime", - "displayName": None, - "shortName": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "previewUrl": None, - "timeZone": None, - "parentFolderId": None, - "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), - "locales": { - "primary": { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "redirect": None, - "subdirectory": None, - "tag": None, - }, - "secondary": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "redirect": None, - "subdirectory": None, - "tag": None, - } - }, - ), - }, - "dataCollectionEnabled": None, - "dataCollectionType": None, - }, - }, - ) - } - response = client.sites.list() - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.list() - validate_response(async_response, expected_response, expected_types) - - -async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "42e98c9a982ac9b8b742", - "workspaceId": "42e63e98c9a982ac9b8b742", - "createdOn": "1979-10-12T12:00:00Z", - "displayName": "The Hitchhiker's Guide to the Galaxy", - "shortName": "hitchhikers-guide", - "lastPublished": "2023-04-02T12:42:00Z", - "lastUpdated": "2023-04-02T12:42:00Z", - "previewUrl": "https://screenshots.webflow.com/sites/6258612d1ee792848f805dcf/20231219211811_d5990556c743f33b7071300a03bf67e6.png", - "timeZone": "Magrathea/FactoryFloor", - "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", - "customDomains": [ - { - "id": "589a331aa51e760df7ccb89d", - "url": "hitchhikersguide.galaxy", - "lastPublished": "2022-12-07T16:51:37Z", - }, - {"id": "589a331aa51e760df7ccb89e", "url": "heartofgold.spaceship", "lastPublished": "2022-12-07T16:51:37Z"}, - ], - "locales": { - "primary": { - "id": "653fd9af6a07fc9cfd7a5e57", - "cmsLocaleId": "653ad57de882f528b32e810e", - "enabled": False, - "displayName": "English (United States)", - "displayImageId": "displayImageId", - "redirect": True, - "subdirectory": "", - "tag": "en-US", - }, - "secondary": [ - { - "id": "653fd9af6a07fc9cfd7a5e57", - "cmsLocaleId": "653ad57de882f528b32e810e", - "enabled": False, - "displayName": "English (United States)", - "redirect": True, - "subdirectory": "", - "tag": "en-US", - } - ], - }, - "dataCollectionEnabled": True, - "dataCollectionType": "always", - } - expected_types: typing.Any = { - "id": None, - "workspaceId": None, - "createdOn": "datetime", - "displayName": None, - "shortName": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "previewUrl": None, - "timeZone": None, - "parentFolderId": None, - "customDomains": ( - "list", - { - 0: {"id": None, "url": None, "lastPublished": "datetime"}, - 1: {"id": None, "url": None, "lastPublished": "datetime"}, - }, - ), - "locales": { - "primary": { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "displayImageId": None, - "redirect": None, - "subdirectory": None, - "tag": None, - }, - "secondary": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "redirect": None, - "subdirectory": None, - "tag": None, - } - }, - ), - }, - "dataCollectionEnabled": None, - "dataCollectionType": None, - } - response = client.sites.get(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.get(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.sites.delete(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.sites.delete(site_id="580e63e98c9a982ac9b8b741") # type: ignore[func-returns-value] - is None - ) - - -async def test_update(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "42e98c9a982ac9b8b742", - "workspaceId": "42e63e98c9a982ac9b8b742", - "createdOn": "1979-10-12T12:00:00Z", - "displayName": "The Hitchhiker's Guide to the Galaxy", - "shortName": "hitchhikers-guide", - "lastPublished": "2023-04-02T12:42:00Z", - "lastUpdated": "2023-04-02T12:42:00Z", - "previewUrl": "https://screenshots.webflow.com/sites/6258612d1ee792848f805dcf/20231219211811_d5990556c743f33b7071300a03bf67e6.png", - "timeZone": "Magrathea/FactoryFloor", - "parentFolderId": "1as2d3f4g5h6j7k8l9z0x1c2v3b4n5m6", - "customDomains": [ - { - "id": "589a331aa51e760df7ccb89d", - "url": "hitchhikersguide.galaxy", - "lastPublished": "2022-12-07T16:51:37Z", - }, - {"id": "589a331aa51e760df7ccb89e", "url": "heartofgold.spaceship", "lastPublished": "2022-12-07T16:51:37Z"}, - ], - "locales": { - "primary": { - "id": "653fd9af6a07fc9cfd7a5e57", - "cmsLocaleId": "653ad57de882f528b32e810e", - "enabled": False, - "displayName": "English (United States)", - "displayImageId": "displayImageId", - "redirect": True, - "subdirectory": "", - "tag": "en-US", - }, - "secondary": [ - { - "id": "653fd9af6a07fc9cfd7a5e57", - "cmsLocaleId": "653ad57de882f528b32e810e", - "enabled": False, - "displayName": "English (United States)", - "redirect": True, - "subdirectory": "", - "tag": "en-US", - } - ], - }, - "dataCollectionEnabled": True, - "dataCollectionType": "always", - } - expected_types: typing.Any = { - "id": None, - "workspaceId": None, - "createdOn": "datetime", - "displayName": None, - "shortName": None, - "lastPublished": "datetime", - "lastUpdated": "datetime", - "previewUrl": None, - "timeZone": None, - "parentFolderId": None, - "customDomains": ( - "list", - { - 0: {"id": None, "url": None, "lastPublished": "datetime"}, - 1: {"id": None, "url": None, "lastPublished": "datetime"}, - }, - ), - "locales": { - "primary": { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "displayImageId": None, - "redirect": None, - "subdirectory": None, - "tag": None, - }, - "secondary": ( - "list", - { - 0: { - "id": None, - "cmsLocaleId": None, - "enabled": None, - "displayName": None, - "redirect": None, - "subdirectory": None, - "tag": None, - } - }, - ), - }, - "dataCollectionEnabled": None, - "dataCollectionType": None, - } - response = client.sites.update(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.update(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_get_custom_domain(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "customDomains": [ - { - "id": "589a331aa51e760df7ccb89d", - "url": "hitchhikersguide.galaxy", - "lastPublished": "2022-12-07T16:51:37Z", - }, - {"id": "589a331aa51e760df7ccb89e", "url": "heartofgold.spaceship", "lastPublished": "2022-12-07T16:51:37Z"}, - ] - } - expected_types: typing.Any = { - "customDomains": ( - "list", - { - 0: {"id": None, "url": None, "lastPublished": "datetime"}, - 1: {"id": None, "url": None, "lastPublished": "datetime"}, - }, - ) - } - response = client.sites.get_custom_domain(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.get_custom_domain(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_publish(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "customDomains": [ - {"id": "589a331aa51e760df7ccb89d", "url": "test-api-domain.com", "lastPublished": "2022-12-07T16:51:37Z"} - ], - "publishToWebflowSubdomain": True, - } - expected_types: typing.Any = { - "customDomains": ("list", {0: {"id": None, "url": None, "lastPublished": "datetime"}}), - "publishToWebflowSubdomain": None, - } - response = client.sites.publish( - site_id="580e63e98c9a982ac9b8b741", - custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], - publish_to_webflow_subdomain=False, - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.sites.publish( - site_id="580e63e98c9a982ac9b8b741", - custom_domains=["660c6449dd97ebc7346ac629", "660c6449dd97ebc7346ac62f"], - publish_to_webflow_subdomain=False, - ) - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_token.py b/tests/test_token.py deleted file mode 100644 index d81bdea..0000000 --- a/tests/test_token.py +++ /dev/null @@ -1,66 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response - - -async def test_authorized_by(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "545bbecb7bdd6769632504a7", - "email": "some@email.com", - "firstName": "Some", - "lastName": "One", - } - expected_types: typing.Any = {"id": None, "email": None, "firstName": None, "lastName": None} - response = client.token.authorized_by() - validate_response(response, expected_response, expected_types) - - async_response = await async_client.token.authorized_by() - validate_response(async_response, expected_response, expected_types) - - -async def test_introspect(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "authorization": { - "id": "55818d58616600637b9a5786", - "createdOn": "2016-10-03T23:12:00Z", - "lastUsed": "2016-10-10T21:41:12Z", - "grantType": "authorization_code", - "rateLimit": 60, - "scope": "assets:read,assets:write", - "authorizedTo": { - "siteIds": ["62f3b1f7eafac55d0c64ef91"], - "workspaceIds": ["52f3b1f7eafac55d0c64ef91"], - "userIds": ["545bbecb7bdd6769632504a7"], - }, - }, - "application": { - "id": "55131cd036c09f7d07883dfc", - "description": "My Amazing App", - "homepage": "https://webflow.com", - "displayName": "My Amazing App", - }, - } - expected_types: typing.Any = { - "authorization": { - "id": None, - "createdOn": "datetime", - "lastUsed": "datetime", - "grantType": None, - "rateLimit": "integer", - "scope": None, - "authorizedTo": { - "siteIds": ("list", {0: None}), - "workspaceIds": ("list", {0: None}), - "userIds": ("list", {0: None}), - }, - }, - "application": {"id": None, "description": None, "homepage": None, "displayName": None}, - } - response = client.token.introspect() - validate_response(response, expected_response, expected_types) - - async_response = await async_client.token.introspect() - validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py deleted file mode 100644 index ea9884c..0000000 --- a/tests/test_webhooks.py +++ /dev/null @@ -1,175 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -from .utilities import validate_response -import datetime - - -async def test_list_(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "webhooks": [ - { - "id": "57ca0a9e418c504a6e1acbb6", - "triggerType": "form_submission", - "url": "https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", - "workspaceId": "4f4e46fd476ea8c507000001", - "siteId": "562ac0395358780a1f5e6fbd", - "filter": {"name": "Email Form"}, - "lastTriggered": "2023-02-08T23:59:28Z", - "createdOn": "2016-09-02T23:26:22Z", - }, - { - "id": "578d85cce0c47cd2865f4cf2", - "triggerType": "form_submission", - "url": "https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", - "workspaceId": "4f4e46fd476ea8c507000001", - "siteId": "562ac0395358780a1f5e6fbd", - "filter": {"name": "Email Form"}, - "lastTriggered": "2023-02-08T23:59:28Z", - "createdOn": "2016-07-19T01:43:40Z", - }, - { - "id": "578d85cce0c47cd2865f4cf3", - "triggerType": "form_submission", - "url": "https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", - "workspaceId": "4f4e46fd476ea8c507000001", - "siteId": "562ac0395358780a1f5e6fbd", - "filter": {"name": "Email Form"}, - "lastTriggered": "2023-02-08T23:59:28Z", - "createdOn": "2016-07-19T01:43:40Z", - }, - ], - "pagination": {"limit": 100, "offset": 0, "total": 100}, - } - expected_types: typing.Any = { - "webhooks": ( - "list", - { - 0: { - "id": None, - "triggerType": None, - "url": None, - "workspaceId": None, - "siteId": None, - "filter": {"name": None}, - "lastTriggered": "datetime", - "createdOn": "datetime", - }, - 1: { - "id": None, - "triggerType": None, - "url": None, - "workspaceId": None, - "siteId": None, - "filter": {"name": None}, - "lastTriggered": "datetime", - "createdOn": "datetime", - }, - 2: { - "id": None, - "triggerType": None, - "url": None, - "workspaceId": None, - "siteId": None, - "filter": {"name": None}, - "lastTriggered": "datetime", - "createdOn": "datetime", - }, - }, - ), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.webhooks.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.webhooks.list(site_id="580e63e98c9a982ac9b8b741") - validate_response(async_response, expected_response, expected_types) - - -async def test_create(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "582266e0cd48de0f0e3c6d8b", - "triggerType": "form_submission", - "url": "https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", - "workspaceId": "4f4e46fd476ea8c507000001", - "siteId": "562ac0395358780a1f5e6fbd", - "filter": {"name": "My Form"}, - "lastTriggered": "2023-02-08T23:59:28Z", - "createdOn": "2022-11-08T23:59:28Z", - } - expected_types: typing.Any = { - "id": None, - "triggerType": None, - "url": None, - "workspaceId": None, - "siteId": None, - "filter": {"name": None}, - "lastTriggered": "datetime", - "createdOn": "datetime", - } - response = client.webhooks.create( - site_id_="580e63e98c9a982ac9b8b741", - id="582266e0cd48de0f0e3c6d8b", - trigger_type="form_submission", - url="https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", - workspace_id="4f4e46fd476ea8c507000001", - site_id="562ac0395358780a1f5e6fbd", - last_triggered=datetime.datetime.fromisoformat("2023-02-08 23:59:28+00:00"), - created_on=datetime.datetime.fromisoformat("2022-11-08 23:59:28+00:00"), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.webhooks.create( - site_id_="580e63e98c9a982ac9b8b741", - id="582266e0cd48de0f0e3c6d8b", - trigger_type="form_submission", - url="https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", - workspace_id="4f4e46fd476ea8c507000001", - site_id="562ac0395358780a1f5e6fbd", - last_triggered=datetime.datetime.fromisoformat("2023-02-08 23:59:28+00:00"), - created_on=datetime.datetime.fromisoformat("2022-11-08 23:59:28+00:00"), - ) - validate_response(async_response, expected_response, expected_types) - - -async def test_get(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "id": "582266e0cd48de0f0e3c6d8b", - "triggerType": "form_submission", - "url": "https://webhook.site/7f7f7f7f-7f7f-7f7f-7f7f-7f7f7f7f7f7f", - "workspaceId": "4f4e46fd476ea8c507000001", - "siteId": "562ac0395358780a1f5e6fbd", - "filter": {"name": "My Form"}, - "lastTriggered": "2023-02-08T23:59:28Z", - "createdOn": "2022-11-08T23:59:28Z", - } - expected_types: typing.Any = { - "id": None, - "triggerType": None, - "url": None, - "workspaceId": None, - "siteId": None, - "filter": {"name": None}, - "lastTriggered": "datetime", - "createdOn": "datetime", - } - response = client.webhooks.get(webhook_id="580e64008c9a982ac9b8b754") - validate_response(response, expected_response, expected_types) - - async_response = await async_client.webhooks.get(webhook_id="580e64008c9a982ac9b8b754") - validate_response(async_response, expected_response, expected_types) - - -async def test_delete(client: Webflow, async_client: AsyncWebflow) -> None: - # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert ( - client.webhooks.delete(webhook_id="580e64008c9a982ac9b8b754") # type: ignore[func-returns-value] - is None - ) - - assert ( - await async_client.webhooks.delete(webhook_id="580e64008c9a982ac9b8b754") # type: ignore[func-returns-value] - is None - ) diff --git a/tests/utilities.py b/tests/utilities.py deleted file mode 100644 index 3d22880..0000000 --- a/tests/utilities.py +++ /dev/null @@ -1,162 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -import typing -import uuid - -from dateutil import parser - -import pydantic - - -def cast_field(json_expectation: typing.Any, type_expectation: typing.Any) -> typing.Any: - # Cast these specific types which come through as string and expect our - # models to cast to the correct type. - if type_expectation == "uuid": - return uuid.UUID(json_expectation) - elif type_expectation == "date": - return parser.parse(json_expectation).date() - elif type_expectation == "datetime": - return parser.parse(json_expectation) - elif type_expectation == "set": - return set(json_expectation) - elif type_expectation == "integer": - # Necessary as we allow numeric keys, but JSON makes them strings - return int(json_expectation) - - return json_expectation - - -def validate_field(response: typing.Any, json_expectation: typing.Any, type_expectation: typing.Any) -> None: - # Allow for an escape hatch if the object cannot be validated - if type_expectation == "no_validate": - return - - is_container_of_complex_type = False - # Parse types in containers, note that dicts are handled within `validate_response` - if isinstance(json_expectation, list): - if isinstance(type_expectation, tuple): - container_expectation = type_expectation[0] - contents_expectation = type_expectation[1] - - cast_json_expectation = [] - for idx, ex in enumerate(json_expectation): - if isinstance(contents_expectation, dict): - entry_expectation = contents_expectation.get(idx) - if isinstance(entry_expectation, dict): - is_container_of_complex_type = True - validate_response( - response=response[idx], - json_expectation=ex, - type_expectations=entry_expectation, - ) - else: - cast_json_expectation.append(cast_field(ex, entry_expectation)) - else: - cast_json_expectation.append(ex) - json_expectation = cast_json_expectation - - # Note that we explicitly do not allow for sets of pydantic models as they are not hashable, so - # if any of the values of the set have a type_expectation of a dict, we're assuming it's a pydantic - # model and keeping it a list. - if container_expectation != "set" or not any( - map( - lambda value: isinstance(value, dict), - list(contents_expectation.values()), - ) - ): - json_expectation = cast_field(json_expectation, container_expectation) - elif isinstance(type_expectation, tuple): - container_expectation = type_expectation[0] - contents_expectation = type_expectation[1] - if isinstance(contents_expectation, dict): - json_expectation = { - cast_field( - key, - contents_expectation.get(idx)[0] # type: ignore - if contents_expectation.get(idx) is not None - else None, - ): cast_field( - value, - contents_expectation.get(idx)[1] # type: ignore - if contents_expectation.get(idx) is not None - else None, - ) - for idx, (key, value) in enumerate(json_expectation.items()) - } - else: - json_expectation = cast_field(json_expectation, container_expectation) - elif type_expectation is not None: - json_expectation = cast_field(json_expectation, type_expectation) - - # When dealing with containers of models, etc. we're validating them implicitly, so no need to check the resultant list - if not is_container_of_complex_type: - assert ( - json_expectation == response - ), "Primitives found, expected: {0} (type: {1}), Actual: {2} (type: {3})".format( - json_expectation, type(json_expectation), response, type(response) - ) - - -# Arg type_expectations is a deeply nested structure that matches the response, but with the values replaced with the expected types -def validate_response(response: typing.Any, json_expectation: typing.Any, type_expectations: typing.Any) -> None: - # Allow for an escape hatch if the object cannot be validated - if type_expectations == "no_validate": - return - - if ( - not isinstance(response, list) - and not isinstance(response, dict) - and not issubclass(type(response), pydantic.BaseModel) - ): - validate_field( - response=response, - json_expectation=json_expectation, - type_expectation=type_expectations, - ) - return - - if isinstance(response, list): - assert len(response) == len(json_expectation), "Length mismatch, expected: {0}, Actual: {1}".format( - len(response), len(json_expectation) - ) - content_expectation = type_expectations - if isinstance(type_expectations, tuple): - content_expectation = type_expectations[1] - for idx, item in enumerate(response): - validate_response( - response=item, - json_expectation=json_expectation[idx], - type_expectations=content_expectation[idx], - ) - else: - response_json = response - if issubclass(type(response), pydantic.BaseModel): - response_json = response.dict(by_alias=True) - - for key, value in json_expectation.items(): - assert key in response_json, "Field {0} not found within the response object: {1}".format( - key, response_json - ) - - type_expectation = None - if type_expectations is not None and isinstance(type_expectations, dict): - type_expectation = type_expectations.get(key) - - # If your type_expectation is a tuple then you have a container field, process it as such - # Otherwise, we're just validating a single field that's a pydantic model. - if isinstance(value, dict) and not isinstance(type_expectation, tuple): - validate_response( - response=response_json[key], - json_expectation=value, - type_expectations=type_expectation, - ) - else: - validate_field( - response=response_json[key], - json_expectation=value, - type_expectation=type_expectation, - ) - - # Ensure there are no additional fields here either - del response_json[key] - assert len(response_json) == 0, "Additional fields found, expected None: {0}".format(response_json) diff --git a/tests/utils/assets/models/__init__.py b/tests/utils/assets/models/__init__.py index 3a1c852..2cf0126 100644 --- a/tests/utils/assets/models/__init__.py +++ b/tests/utils/assets/models/__init__.py @@ -5,7 +5,7 @@ from .circle import CircleParams from .object_with_defaults import ObjectWithDefaultsParams from .object_with_optional_field import ObjectWithOptionalFieldParams -from .shape import ShapeParams, Shape_CircleParams, Shape_SquareParams +from .shape import Shape_CircleParams, Shape_SquareParams, ShapeParams from .square import SquareParams from .undiscriminated_shape import UndiscriminatedShapeParams diff --git a/tests/utils/assets/models/circle.py b/tests/utils/assets/models/circle.py index de001b7..9295a33 100644 --- a/tests/utils/assets/models/circle.py +++ b/tests/utils/assets/models/circle.py @@ -3,7 +3,7 @@ # This file was auto-generated by Fern from our API Definition. import typing_extensions -import typing_extensions + from webflow.core.serialization import FieldMetadata diff --git a/tests/utils/assets/models/object_with_defaults.py b/tests/utils/assets/models/object_with_defaults.py index ef14f7b..a977b1d 100644 --- a/tests/utils/assets/models/object_with_defaults.py +++ b/tests/utils/assets/models/object_with_defaults.py @@ -3,7 +3,6 @@ # This file was auto-generated by Fern from our API Definition. import typing_extensions -import typing_extensions class ObjectWithDefaultsParams(typing_extensions.TypedDict): diff --git a/tests/utils/assets/models/object_with_optional_field.py b/tests/utils/assets/models/object_with_optional_field.py index 1912220..f1a588e 100644 --- a/tests/utils/assets/models/object_with_optional_field.py +++ b/tests/utils/assets/models/object_with_optional_field.py @@ -2,16 +2,17 @@ # This file was auto-generated by Fern from our API Definition. -import typing_extensions -import typing -import typing_extensions -from webflow.core.serialization import FieldMetadata import datetime as dt +import typing import uuid + +import typing_extensions from .color import Color from .shape import ShapeParams from .undiscriminated_shape import UndiscriminatedShapeParams +from webflow.core.serialization import FieldMetadata + class ObjectWithOptionalFieldParams(typing_extensions.TypedDict): literal: typing.Literal["lit_one"] diff --git a/tests/utils/assets/models/shape.py b/tests/utils/assets/models/shape.py index cf58a9b..84153dc 100644 --- a/tests/utils/assets/models/shape.py +++ b/tests/utils/assets/models/shape.py @@ -3,9 +3,11 @@ # This file was auto-generated by Fern from our API Definition. from __future__ import annotations -import typing_extensions -import typing_extensions + import typing + +import typing_extensions + from webflow.core.serialization import FieldMetadata diff --git a/tests/utils/assets/models/square.py b/tests/utils/assets/models/square.py index ec068c5..3f40c1f 100644 --- a/tests/utils/assets/models/square.py +++ b/tests/utils/assets/models/square.py @@ -3,7 +3,7 @@ # This file was auto-generated by Fern from our API Definition. import typing_extensions -import typing_extensions + from webflow.core.serialization import FieldMetadata diff --git a/tests/utils/assets/models/undiscriminated_shape.py b/tests/utils/assets/models/undiscriminated_shape.py index 68876a2..99f12b3 100644 --- a/tests/utils/assets/models/undiscriminated_shape.py +++ b/tests/utils/assets/models/undiscriminated_shape.py @@ -3,6 +3,7 @@ # This file was auto-generated by Fern from our API Definition. import typing + from .circle import CircleParams from .square import SquareParams diff --git a/tests/utils/test_http_client.py b/tests/utils/test_http_client.py index 8532616..10ef8a1 100644 --- a/tests/utils/test_http_client.py +++ b/tests/utils/test_http_client.py @@ -1,13 +1,57 @@ # This file was auto-generated by Fern from our API Definition. -from webflow.core.http_client import get_request_body +from typing import Any, Dict + +import pytest + +from webflow.core.http_client import ( + AsyncHttpClient, + HttpClient, + _build_url, + get_request_body, + remove_none_from_dict, +) from webflow.core.request_options import RequestOptions +# Stub clients for testing HttpClient and AsyncHttpClient +class _DummySyncClient: + """A minimal stub for httpx.Client that records request arguments.""" + + def __init__(self) -> None: + self.last_request_kwargs: Dict[str, Any] = {} + + def request(self, **kwargs: Any) -> "_DummyResponse": + self.last_request_kwargs = kwargs + return _DummyResponse() + + +class _DummyAsyncClient: + """A minimal stub for httpx.AsyncClient that records request arguments.""" + + def __init__(self) -> None: + self.last_request_kwargs: Dict[str, Any] = {} + + async def request(self, **kwargs: Any) -> "_DummyResponse": + self.last_request_kwargs = kwargs + return _DummyResponse() + + +class _DummyResponse: + """A minimal stub for httpx.Response.""" + + status_code = 200 + headers: Dict[str, str] = {} + + def get_request_options() -> RequestOptions: return {"additional_body_parameters": {"see you": "later"}} +def get_request_options_with_none() -> RequestOptions: + return {"additional_body_parameters": {"see you": "later", "optional": None}} + + def test_get_json_request_body() -> None: json_body, data_body = get_request_body(json={"hello": "world"}, data=None, request_options=None, omit=None) assert json_body == {"hello": "world"} @@ -48,14 +92,209 @@ def test_get_none_request_body() -> None: def test_get_empty_json_request_body() -> None: + """Test that implicit empty bodies (json=None) are collapsed to None.""" unrelated_request_options: RequestOptions = {"max_retries": 3} json_body, data_body = get_request_body(json=None, data=None, request_options=unrelated_request_options, omit=None) assert json_body is None assert data_body is None - json_body_extras, data_body_extras = get_request_body( - json={}, data=None, request_options=unrelated_request_options, omit=None + +def test_explicit_empty_json_body_is_preserved() -> None: + """Test that explicit empty bodies (json={}) are preserved and sent as {}. + + This is important for endpoints where the request body is required but all + fields are optional. The server expects valid JSON ({}) not an empty body. + """ + unrelated_request_options: RequestOptions = {"max_retries": 3} + + # Explicit json={} should be preserved + json_body, data_body = get_request_body(json={}, data=None, request_options=unrelated_request_options, omit=None) + assert json_body == {} + assert data_body is None + + # Explicit data={} should also be preserved + json_body2, data_body2 = get_request_body(json=None, data={}, request_options=unrelated_request_options, omit=None) + assert json_body2 is None + assert data_body2 == {} + + +def test_json_body_preserves_none_values() -> None: + """Test that JSON bodies preserve None values (they become JSON null).""" + json_body, data_body = get_request_body( + json={"hello": "world", "optional": None}, data=None, request_options=None, omit=None ) + # JSON bodies should preserve None values + assert json_body == {"hello": "world", "optional": None} + assert data_body is None - assert json_body_extras is None - assert data_body_extras is None + +def test_data_body_preserves_none_values_without_multipart() -> None: + """Test that data bodies preserve None values when not using multipart. + + The filtering of None values happens in HttpClient.request/stream methods, + not in get_request_body. This test verifies get_request_body doesn't filter None. + """ + json_body, data_body = get_request_body( + json=None, data={"hello": "world", "optional": None}, request_options=None, omit=None + ) + # get_request_body should preserve None values in data body + # The filtering happens later in HttpClient.request when multipart is detected + assert data_body == {"hello": "world", "optional": None} + assert json_body is None + + +def test_remove_none_from_dict_filters_none_values() -> None: + """Test that remove_none_from_dict correctly filters out None values.""" + original = {"hello": "world", "optional": None, "another": "value", "also_none": None} + filtered = remove_none_from_dict(original) + assert filtered == {"hello": "world", "another": "value"} + # Original should not be modified + assert original == {"hello": "world", "optional": None, "another": "value", "also_none": None} + + +def test_remove_none_from_dict_empty_dict() -> None: + """Test that remove_none_from_dict handles empty dict.""" + assert remove_none_from_dict({}) == {} + + +def test_remove_none_from_dict_all_none() -> None: + """Test that remove_none_from_dict handles dict with all None values.""" + assert remove_none_from_dict({"a": None, "b": None}) == {} + + +def test_http_client_does_not_pass_empty_params_list() -> None: + """Test that HttpClient passes params=None when params are empty. + + This prevents httpx from stripping existing query parameters from the URL, + which happens when params=[] or params={} is passed. + """ + dummy_client = _DummySyncClient() + http_client = HttpClient( + httpx_client=dummy_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + ) + + # Use a path with query params (e.g., pagination cursor URL) + http_client.request( + path="resource?after=123", + method="GET", + params=None, + request_options=None, + ) + + # We care that httpx receives params=None, not [] or {} + assert "params" in dummy_client.last_request_kwargs + assert dummy_client.last_request_kwargs["params"] is None + + # Verify the query string in the URL is preserved + url = str(dummy_client.last_request_kwargs["url"]) + assert "after=123" in url, f"Expected query param 'after=123' in URL, got: {url}" + + +def test_http_client_passes_encoded_params_when_present() -> None: + """Test that HttpClient passes encoded params when params are provided.""" + dummy_client = _DummySyncClient() + http_client = HttpClient( + httpx_client=dummy_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com/resource", + ) + + http_client.request( + path="", + method="GET", + params={"after": "456"}, + request_options=None, + ) + + params = dummy_client.last_request_kwargs["params"] + # For a simple dict, encode_query should give a single (key, value) tuple + assert params == [("after", "456")] + + +@pytest.mark.asyncio +async def test_async_http_client_does_not_pass_empty_params_list() -> None: + """Test that AsyncHttpClient passes params=None when params are empty. + + This prevents httpx from stripping existing query parameters from the URL, + which happens when params=[] or params={} is passed. + """ + dummy_client = _DummyAsyncClient() + http_client = AsyncHttpClient( + httpx_client=dummy_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com", + async_base_headers=None, + ) + + # Use a path with query params (e.g., pagination cursor URL) + await http_client.request( + path="resource?after=123", + method="GET", + params=None, + request_options=None, + ) + + # We care that httpx receives params=None, not [] or {} + assert "params" in dummy_client.last_request_kwargs + assert dummy_client.last_request_kwargs["params"] is None + + # Verify the query string in the URL is preserved + url = str(dummy_client.last_request_kwargs["url"]) + assert "after=123" in url, f"Expected query param 'after=123' in URL, got: {url}" + + +@pytest.mark.asyncio +async def test_async_http_client_passes_encoded_params_when_present() -> None: + """Test that AsyncHttpClient passes encoded params when params are provided.""" + dummy_client = _DummyAsyncClient() + http_client = AsyncHttpClient( + httpx_client=dummy_client, # type: ignore[arg-type] + base_timeout=lambda: None, + base_headers=lambda: {}, + base_url=lambda: "https://example.com/resource", + async_base_headers=None, + ) + + await http_client.request( + path="", + method="GET", + params={"after": "456"}, + request_options=None, + ) + + params = dummy_client.last_request_kwargs["params"] + # For a simple dict, encode_query should give a single (key, value) tuple + assert params == [("after", "456")] + + +def test_basic_url_joining() -> None: + """Test basic URL joining with a simple base URL and path.""" + result = _build_url("https://api.example.com", "/users") + assert result == "https://api.example.com/users" + + +def test_basic_url_joining_trailing_slash() -> None: + """Test basic URL joining with a simple base URL and path.""" + result = _build_url("https://api.example.com/", "/users") + assert result == "https://api.example.com/users" + + +def test_preserves_base_url_path_prefix() -> None: + """Test that path prefixes in base URL are preserved. + + This is the critical bug fix - urllib.parse.urljoin() would strip + the path prefix when the path starts with '/'. + """ + result = _build_url("https://cloud.example.com/org/tenant/api", "/users") + assert result == "https://cloud.example.com/org/tenant/api/users" + + +def test_preserves_base_url_path_prefix_trailing_slash() -> None: + """Test that path prefixes in base URL are preserved.""" + result = _build_url("https://cloud.example.com/org/tenant/api/", "/users") + assert result == "https://cloud.example.com/org/tenant/api/users" diff --git a/tests/utils/test_query_encoding.py b/tests/utils/test_query_encoding.py index 9c4591e..c76b5d2 100644 --- a/tests/utils/test_query_encoding.py +++ b/tests/utils/test_query_encoding.py @@ -1,6 +1,5 @@ # This file was auto-generated by Fern from our API Definition. - from webflow.core.query_encoder import encode_query @@ -34,4 +33,4 @@ def test_query_encoding_deep_object_arrays() -> None: def test_encode_query_with_none() -> None: encoded = encode_query(None) - assert encoded == None + assert encoded is None diff --git a/tests/utils/test_serialization.py b/tests/utils/test_serialization.py index 3676b2f..af7b043 100644 --- a/tests/utils/test_serialization.py +++ b/tests/utils/test_serialization.py @@ -1,10 +1,10 @@ # This file was auto-generated by Fern from our API Definition. -from typing import List, Any +from typing import Any, List -from webflow.core.serialization import convert_and_respect_annotation_metadata -from .assets.models import ShapeParams, ObjectWithOptionalFieldParams +from .assets.models import ObjectWithOptionalFieldParams, ShapeParams +from webflow.core.serialization import convert_and_respect_annotation_metadata UNION_TEST: ShapeParams = {"radius_measurement": 1.0, "shape_type": "circle", "id": "1"} UNION_TEST_CONVERTED = {"shapeType": "circle", "radiusMeasurement": 1.0, "id": "1"} diff --git a/tests/workspaces/__init__.py b/tests/workspaces/__init__.py deleted file mode 100644 index f3ea265..0000000 --- a/tests/workspaces/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - diff --git a/tests/workspaces/test_audit_logs.py b/tests/workspaces/test_audit_logs.py deleted file mode 100644 index eb7ea27..0000000 --- a/tests/workspaces/test_audit_logs.py +++ /dev/null @@ -1,61 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from webflow import Webflow -from webflow import AsyncWebflow -import typing -import datetime -from ..utilities import validate_response - - -async def test_get_workspace_audit_logs(client: Webflow, async_client: AsyncWebflow) -> None: - expected_response: typing.Any = { - "items": [ - { - "eventSubType": "login", - "eventType": "user_access", - "timestamp": "2025-04-29T20:30:06Z", - "actor": {"id": "6661ccb359b561c69f29d554", "email": "someone@email.com"}, - "workspace": {"id": "6621ccb459b561c69f29d57c", "slug": "hitchhikers-workspace"}, - }, - { - "eventSubType": "user_added", - "eventType": "workspace_membership", - "timestamp": "2025-04-30T20:30:06Z", - "actor": {"id": "60492e55bbddce079561cd7a", "email": "someone@webflow.com"}, - "workspace": {"id": "6621ccb459b561c69f29d57c", "slug": "hitchhikers-workspace"}, - }, - { - "eventSubType": "user_added", - "eventType": "site_membership", - "timestamp": "2025-04-30T00:33:31Z", - "actor": {"id": "671fe00d185fc8c1ad409d37", "email": "someone@webflow.com"}, - "workspace": {"id": "6621ccb459b561c69f29d57c", "slug": "hitchhikers-workspace"}, - }, - ], - "pagination": {"limit": 10, "offset": 0, "total": 3}, - } - expected_types: typing.Any = { - "items": ("list", {0: "no_validate", 1: "no_validate", 2: "no_validate"}), - "pagination": {"limit": "integer", "offset": "integer", "total": "integer"}, - } - response = client.workspaces.audit_logs.get_workspace_audit_logs( - workspace_id_or_slug="hitchhikers-workspace", - limit=1, - offset=1, - sort_order="asc", - event_type="user_access", - from_=datetime.datetime.fromisoformat("2025-06-22 16:00:31+00:00"), - to=datetime.datetime.fromisoformat("2025-07-22 16:00:31+00:00"), - ) - validate_response(response, expected_response, expected_types) - - async_response = await async_client.workspaces.audit_logs.get_workspace_audit_logs( - workspace_id_or_slug="hitchhikers-workspace", - limit=1, - offset=1, - sort_order="asc", - event_type="user_access", - from_=datetime.datetime.fromisoformat("2025-06-22 16:00:31+00:00"), - to=datetime.datetime.fromisoformat("2025-07-22 16:00:31+00:00"), - ) - validate_response(async_response, expected_response, expected_types) From f8b81bdb0d5298332b863a4c3465de505b78808b Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 13:39:56 +0000 Subject: [PATCH 13/13] SDK regeneration --- .fern/metadata.json | 2 +- pyproject.toml | 2 +- src/webflow/core/client_wrapper.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.fern/metadata.json b/.fern/metadata.json index c585311..44a2882 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -10,5 +10,5 @@ } }, "originGitCommit": "3ad89f5558f1774e8535f034a87bfe8c2fdfcd50", - "sdkVersion": "1.2.1" + "sdkVersion": "2.0.0" } \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index bec7144..786103a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ dynamic = ["version"] [tool.poetry] name = "webflow" -version = "1.2.1" +version = "2.0.0" description = "" readme = "README.md" authors = [] diff --git a/src/webflow/core/client_wrapper.py b/src/webflow/core/client_wrapper.py index 39a2e70..7f6db17 100644 --- a/src/webflow/core/client_wrapper.py +++ b/src/webflow/core/client_wrapper.py @@ -28,12 +28,12 @@ def get_headers(self) -> typing.Dict[str, str]: import platform headers: typing.Dict[str, str] = { - "User-Agent": "webflow/1.2.1", + "User-Agent": "webflow/2.0.0", "X-Fern-Language": "Python", "X-Fern-Runtime": f"python/{platform.python_version()}", "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}", "X-Fern-SDK-Name": "webflow", - "X-Fern-SDK-Version": "1.2.1", + "X-Fern-SDK-Version": "2.0.0", **(self.get_custom_headers() or {}), } headers["Authorization"] = f"Bearer {self._get_access_token()}"